Translating Time in the Text: A(nother) Chinese Calendar Converter

This article is an interlude between the usual posts, introducing a python-based toolkit called ChineseCalendarTools (available on gitlab, together with documentation and examples of usage). [1] The toolkit provides code for parsing and converting Chinese lunisolar dates from the Qing (1644-1912) and Republican Era (1912-1949). Without delving too much into the technical details, this post gives the reader a window on why a calendar converter in code form exists in the first place, how it operates and what to expect next.

I needed some code…

The story goes back to when I made my first prototype more than a year ago. During the Digital Zhang Gang project I had the task to convert over 15,000 dates from the Chinese lunisolar Calendar, specifically the Qing and the Republican Era, to Gregorian calendar. Originally, I wanted to automate the task using the conversion tool of Academia Sinica (兩千年中西曆轉換). However, the tool could only take in 1,000 entries at the time of writing, which was not ideal for situations in which a larger quantity of data had to be processed. Due to the lack of suitable alternatives at the time, I decided to build a digital calendar converter of my own. [2] I fetched the chronological information about the Qing and Republican Era from the Academia Sinica platform and created an R-language based program on top of the extracted data.

The workings of the prototype were basic: the calendar conversion hinged on searching a one-to-one match in a large data table, containing over 121,000 pairs of Gregorian and Qing/Republican dates. One just needed to put in the information of a Chinese date, which enabled the code to query the dataset and pull out the right result.

Sample R-code: The function get_gregorian_date(…) requires the following parameters: dynasty name, reign name, year (number), number of lunar month, TRUE or FALSE of the date containing an intercalary month and number of lunar day. The code will use the input values to search the corresponding Gregorian date in a large dataset.

The prototype did an overall satisfying job, yet its usage was very limited. Just from the sample code above, we can derive two issues regarding to the input for the script:

  1. The script depends on structured data to work. It assumes that the user already split up the Chinese date and ‘translated’ all components to the expected format. Even though it might not have been a problem for the project mentioned above, it will be for Chinese dates that are most likely to come from textual sources. This mismatch between the expected input and actual form of dates will require pre-processing for almost each new set of dates before we introduce them to the converter.
  2. The input only accepts one type of Chinese date, namely dates that have years and days expressed in numbers. Dates that deploys sexagenary cycle (六十干支) or other terms such as wangri 望日 are excluded from the process.

These issues raised the question of whether merely retrieving from a dataset was sufficient to expect from a digital calendar converter, especially in the context of date extraction and processing. As a result, I took time to think differently about the whole process of handling Chinese dates and created another version of the calendar converter, this time in Python.

To the drawing board and back

overview procedure

The current digital calendar converter differs from the previous version in two aspects: the textual input and data size.

When using the calendar converter, the user only has to provide the Chinese date in text form. The basic idea is that the script does some pre-processing on the input date: it splits the date into meaningful parts (period, nianhao, year number, etc.), adds extra information where possible (e.g. the corresponding day ganzhi) and put the different date components to use for various tasks, such as conversion. This “one-time input” also means that dates can be parsed in different forms. For example, it parses “光緒二十六年正月二十一日” also as “光緒庚子正月廿一號” or “光緒二十六年正月乙丑”.

Unlike with the previous version, the date conversion depends on less data. In the beginning, there was this (quite ambitious) idea to depend on a comprehensive formula for calculating dates, minimizing the need of retrieving data. However, because of my limited knowledge of calendar-related algorithms, the current calendar converter follows a procedure that forms the middle ground between data retrieval and calculation. For this, I took inspiration from an “analogue” calendar conversion work of 1910: Concordance des Chronologies Néoméniques chinoise et Européenne by P. Hoang. [3] The work presents every reigning period from a dynasty as a compact fiche, showing the first day of the lunar months (see second column) with the corresponding month (third) and day (fourth) in Gregorian calendar as well as other kind of information. In order to calculate the correct Gregorian date, one look ups the right reigning period, retrieves the beginning Gregorian date of the relevant lunar month and adds to that date the number of days one needs to get to the Chinese date. This way of storing and converting chronological data forms the backbone of the calendar converter.

Photo |Source: Concordance des chronologies néoméniques chinoise et européenne.

In essence, the current version has a more expanded pipeline that automatically prepares the date before any task needs to be done, while operating on less data. It is not without its flaws, such as how it deals with the ambiguous date 康熙壬寅年 (i.e. first/last year of the Kangxi reign), and the caliber of the output depends greatly on the accuracy of the chronological data. Nevertheless, it answers the particular need of treating dates in their “rawest” form and offers a more flexible way to manipulate and convert dates (see the code samples below).

Sample Python-code 1: First, one has to pass a string containing the Chinese date as input for LuniSolarCalendar(…). Then one can query the actual lunar day from that date.
Sample Python-code 2: Once the input date is set up, one can call the .convert_ls_date() function to convert the date.

Where to go next

At the moment the Chinese calendar converter, which consists of a single script and a modified version of the Academia Sinica dataset, is brought under the gitlab project ChineseCalendarTools. As the name suggests, I plan to expand on the type of tasks related to processing historical time. I have already made functions to the code, such as converting ganzhi from text to number (and vice versa), estimating the ganzhi of a Gregorian year or extracting Qing or minguo dates from text. The new additions will mostly address what problems arise during the ENP-China project and need to be automated. Other than that, suggestions are always welcome!

[1] For those who are not familiar with programming (or wince at the idea of it), there is an online application that executes the calendar conversion script, albeit limited in output format.

[2] There exists a python-package that does Chinese-Gregorian calendar conversion (called ‘lunisolar’) but from the examples of usage the script does not seem to have reign years as part of the input. Link: https://pypi.org/project/lunisolar/ [last accessed on 2022-1-31]

[3] Hoang, P., Concordance des chronologies néoméniques chinoise et européenne,
(Variétés sinologiques 29), Shanghai: Mission catholique, 1910.


You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.