Predicting the Six Days of the Japanese Calendar using Python

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:

$ ./python/sixdays.py
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 .bashrc: en_US.UTF-8

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[0]
            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.

Advertisements

Author: Doug

A fellow who dwells upon the Pale Blue Dot who spends his days obsessing over things like Buddhism, KPop music, foreign languages, BSD UNIX and science fiction.

1 thought on “Predicting the Six Days of the Japanese Calendar using Python”

  1. Can you repost the code with proper spacing? I can’t get it to work. Every time I try to run it, the command line complains about paragraphs not where expected. I don’t know enough about python to know how everything should be properly spaced.

    Like

Comments are closed.