Lately, I’ve been struggling to learn a programming language called Python. I know how to program using Perl and BASH, but a lot of people where I work use Python, and many technicians should know at least 2 scripting languages in their career, so I am learning Python now.
The best way to learn of course is to start writing programs, or editing other people’s programs. Just like learning a real language. 😉
So, I decided to try and solve a program, that turned out to be pretty challenging. A long time ago, I wrote a post about the “six days” of the traditional Japanese calendar, or rokuyō (六曜). I decided it would be an interseting challenge to write a program that would tell me which day it was, such as tomobiki (友引), taian (大安), etc.
Finally I got it to work. Here’s what it looks like on my Linux box:
Today is: Tuesday February 04, 2014, Taian 大安
This is a good day for new undertaking or social events.
Or, give it a different day:
$ ./sixdays.py -d 2014-11-10
Today is: Monday November 10, 2014, Butsumetsu 仏滅
Social events and new undertakings are not advised today.
However, making this work turned out to be really tricky. The reason is that the cycle of days in the traditional Japanese calendar was pretty complicated. I had to use a calendar like this one to figure out what the pattern was, then write a code to do the same thing.
The pattern is like so:
- The “year” begins on Chinese New Year which is kyūshōgatsu in Japanese (旧正月).
- The “months” are 30 days or 31 days. If it is an odd-numbered month, it is 30 days, or 31 days for an even-numbered month (2,4,6, etc)
- Each month rotates through the same six days over and over.
- However each month starts with a different day. The first mynah starts with senshō 先勝, but month 2 starts with tomobiki 友引. So the starting point for each month rotates.
I am not a good python programmer, so the code here isn’t great. It’s good enough. Maybe someday I’ll go back and make it look nicer, or handle timezones better.
Also, to make the kanji display correctly on my (Ubuntu) desktop,I had to set this variable in
Anyway, here’s the code itself:
#!/usr/bin/python # -*- coding: utf8 -*- from datetime import datetime, timedelta from collections import deque import argparse import sys def usage(err): print str(err) # will print something like "option -a not recognized" sys.exit(1) def main(argv): # Strftime time format fmt = '%A %B %d, %Y' # The six days in the Japanese traditional calendar, per: # https://en.wikipedia.org/wiki/Japanese_calendar#Rokuy.C5.8D days = ['Sensho 先勝', 'Tomobiki 友引', 'Senbu 先負', 'Butsumetsu 仏滅', 'Taian 大安', 'Shakko 赤口'] fortune = [ 'First part of the day is lucky, afternoon is unlucky.', 'Beware funerals on this day, social events are good though.', 'First part of the day is unlucky, afternoon is lucky.', 'Social events and new undertakings are not advised today.', 'This is a good day for new undertakings or social events.', 'Beware of knives and fire. 11am to 1pm is OK.', ] # Our anchor date, which is the first day of lunar year # or kyuu-shougatsu in Japanese anchor = datetime(2014, 1, 31) # Sundry variables we need date = None verbose = False # Parse arguments using argparse module parser = argparse.ArgumentParser(description='Date/time script using Japanese Rokuyo calendar.') parser.add_argument('--verbose', action="store_true", dest="verbose", default=False, help="Set debug output. Default is false.") parser.add_argument('--date', action="store", dest="date", help="Choose a future date other than today. Format is YYYY-MM-DD.") args = parser.parse_args() # Set flags as required if args.verbose: verbose = True if args.date: date = args.date # If no date is specified, just use today's date if not date: if verbose: print "Using today's date." date = datetime.today() else: date = datetime.strptime(date, '%Y-%m-%d') delta = date - anchor if verbose: print "Days apart:", delta.days # Offset by month of the year month_offset = delta.days / 30 if verbose: print "Month offset:", month_offset # Also, get the extra day offset per month day_offset = (delta.days % 30) # Subtract one extra day for every even numbered-month # because the Lunar calendar is just that confusing. if verbose: print "Day offset:", day_offset for i in range(month_offset): if (i % 2 == 0): day_offset += 1 if verbose: print "Shifting array" # Shift the first "day" to the back of the line #offset = days.pop days.insert(-1, days.pop(0)) # Repeat for the matching fortune fortune.insert(-1, fortune.pop(0)) if verbose: print "The array is shifted as follows:" print days print "Today is: %s, %s" % (date.strftime(fmt), days[day_offset % 6]) print fortune[day_offset % 6], "n" if __name__ == "__main__": main(sys.argv[1:])
Feel free to leave comments or improve on it.