You are here: irt.org | Articles | JavaScript | Date and Time | The Chinese New Year [ previous next ]
Published on: Saturday 1st November 1997 By: Martin Webb
This article describes how to show the year of the chinese calendar that a date falls in, including the dates and days for the year.
The following additional arrays are utilised in this article, using the makeArray() function described in Blind Date:
var chinese = new makeArray('Rat','Ox','Tiger','Hare', 'Dragon','Snake','Horse','Sheep', 'Monkey','Fowl','Dog','Pig'); var branches = new makeArray('Zi','Chou','Yin','Mao', 'Chen','Si','Wu','Wei', 'Shen','You','Xu','Hai'); var stems = new makeArray('Jia','Yi','bing','Ding','Wu', 'Ji','Geng','Xin','Ren','Gui');
The Chinese year names have a sixty-year cycle, and are created by pairing a Celestrial Stem with a Terrestrial Branch. The Celestial Stems are specified by Chinese characters that have no English translation; the Terrestrial Branches are named after twelve animals.
chinese[ ] | branches[ ] | stems[ ] |
Rat | Zi | Jia |
Ox | Chou | Yi |
Tiger | Yin | Bing |
Hare | Mao | Ding |
Dragon | Chen | Wu |
Snake | Si | Ji |
Horse | Wu | Geng |
Sheep | Wei | Xin |
Monkey | Shen | Ren |
Fowl | You | Gui |
Dog | Xu | |
Pig | Hai |
The initial year (jia-zi) of the current cycle began on 1984 February 2. The full list of the sexagenary year names is as follows:
# | Year Names | # | Year Names | # | Year Names | # | Year Names |
1. | Jia-Zi | 16. | Ji-Mao | 31. | Jia-Wu | 46. | Ji-You |
2. | Yi-Chou | 17. | Geng-Chen | 32. | Yi-Wei | 47. | Geng-Xu |
3. | Bing-Yin | 18. | Xin-Si | 33. | Bing-Shen | 48. | Xin-Hai |
4. | Ding-Mao | 19. | Ren-Wu | 34. | Ding-You | 49. | Ren-Zi |
5. | Wu-Chen | 20. | Gui-Wei | 35. | Wu-Xu | 50. | Gui-Chou |
6. | Ji-Si | 21. | Jia-Shen | 36. | Ji-Hai | 51. | Jia-Yin |
7. | Geng-Wu | 22. | Yi-You | 37. | Geng-Zi | 52. | Yi-Mao |
8. | Xin-Wei | 23. | Bing-Xu | 38. | Xin-Chou | 53. | Bing-Chen |
9. | Ren-Shen | 24. | Ding-Hai | 39. | Ren-Yin | 54. | Ding-Si |
10. | Gui-You | 25. | Wu-Zi | 40. | Gui-Mao | 55. | Wu-Wu |
11. | Jia-Xu | 26. | Ji-Chou | 41. | Jia-Chen | 56. | Ji-Wei |
12. | Yi-Hai | 27. | Geng-Yin | 42. | Yi-Si | 57. | Geng-Shen |
13. | Bing-Zi | 28. | Xin-Mao | 43. | Bing-Wu | 58. | Xin-You |
14. | Ding-chou | 29. | Ren-Chen | 44. | Ding-Wei | 59. | Ren-Xu |
15. | Wu-Yin | 30. | gui-Si | 45. | Wu-Shen | 60. | Gui-Hai |
The Chinese celebrate New Year's Day sometime between January 10th and February 19th of the Gregorian calendar.
The following chinesenewyear[] array holds the dates of the Chinese New Year from 1900 to 1999, in the format M.DD, where M is the number of the month, and DD is the date within the month M:
var chinesenewyear = new makeArray(1.31,2.19,2.08,1.29,2.16,2.04,1.25,2.13,2.02,1.22, 2.10,1.30,2.18,2.06,1.26,2.14,2.03,1.23,2.11,2.01, 2.20,2.08,1.28,2.16,2.05,1.25,2.13,2.02,1.23,2.10, 1.30,2.17,2.06,1.26,2.14,2.04,1.24,2.11,1.31,2.19, 2.08,1.27,2.15,2.05,1.25,2.13,2.02,1.22,2.10,1.29, 2.17,2.06,1.27,2.14,2.03,1.24,2.12,1.31,2.18,2.08, 1.28,2.15,2.05,1.25,2.13,2.02,1.21,2.09,1.30,2.17, 2.06,1.27,2.15,2.03,1.23,2.11,1.31,2.18,2.07,1.28, 2.16,2.05,1.25,2.13,2.02,2.20,2.09,1.29,2.17,2.06, 1.27,2.15,2.04,1.23,2.10,1.31,2.19,2.07,1.28,2.16);
So for example in 1900 the Chinese New Year fell on 1.31, i.e. the 31st of January. For years outside this range, only a rough estimate of the animal associated with each year is calculated.
Not unlike a leap year, where you simple divide the year with 4, 100, or 400 to test whether or not a year is a leap year, to calculate the Chinese branch, you must first subtract 3 from the year before dividing by 12 to find out which animal is associated with the year:
number = (year - 3)%12;
So for example, for 1997:
To retrieve the Chinese stem, it is necessary to subtract 3 from the year and then divide by 10:
number = (year - 3)%10;
So for 1997:
Therefore 1997 was the Chinese year Chou-Ding, or the year of the Ox.
However, life is not that simple. As mentioned, the start of the Chinese New Year varies from January 10th to February 19th. People always think that because I was born in 1965 then that means I was born in the year of the Snake. But because I was born on the 4th January, I was actually born in the year of the Dragon.
By testing the start of the Chinese New Year, we can account for this. Rather than calculate the beginning of the Chinese New Year, which may even be beyond the capability of JavaScript (although I am currently working on this), we'll use the chinesenewyear[] array described above.
To retrieve the details for any particular year from 1900 to 1999 we use the following:
var number = chinesenewyear[year - 1899];
To retrieve the month and day from a floating point number, e.g. 9.99, we use the following:
var month = Math.floor(number); var day = Math.round((number*100)-(month*100));
Then all we need to do is compare the date entered with the start of the Chinese New Year, if its the same or greater then it is a simple matter of retrieving the chinese branch for the year, and if its less than then it requires retrieving the chinese branch for the previous year:
if ((month > newMonth) || ((month == newMonth) && (day >= newDay))) { var chineseBranch = (year-3)%12; var chineseStem = (year-3)%10; } else { var chineseBranch = (year-4)%12; var chineseStem = (year-4)%10; }
The following Chinese() function does all of this and more. It returns the animal name for the day, month and year passed, and also calculates the values of chineseyearrange the Chinese year range for the date, and chineseyearname the full name of the Chinese year.
The chineseyearrange can only be correctly returned for the years 1901 to 1998, as we must have the values for the years before 1901 and after 1998 to correctly calculate the start and end of the relevant years.
It also makes use of the FullDate() function described in the previous article Monday's child is full of grace
function Chinese(day,month,year) { if ((year > 1900) && (year < 1999)) { var newYear = chinesenewyear[year - 1899]; var newMonth = Math.floor(newYear); var newDay = Math.round((newYear*100)-(newMonth*100)); if ((month > newMonth) || ((month == newMonth) && (day >= newDay))) { // this year var chineseBranch = (year-3)%12; var chineseStem = (year-3)%10; var nextYear = chinesenewyear[year - 1899 + 1]; var nextMonth = Math.floor(nextYear); var nextDay = Math.round((nextYear*100)-(nextMonth*100)); var lastDay = nextDay - 1; if (lastDay == 0) { lastMonth = nextMonth - 1; lastDay = 31; } else lastMonth = nextMonth; chineseyearrange = FullDate(newDay,newMonth,year) + ' - ' + FullDate(lastDay,lastMonth,year+1); } else { // last year var chineseBranch = (year-4)%12; var chineseStem = (year-4)%10; var oldYear = chinesenewyear[year - 1899 - 1]; var oldMonth = Math.floor(oldYear); var oldDay = Math.round((oldYear*100)-(oldMonth*100)); var lastDay = newDay - 1; if (lastDay == 0) { lastMonth = newMonth - 1; lastDay = 31; } else lastMonth = newMonth; chineseyearrange = FullDate(oldDay,oldMonth,year-1) + ' ' + FullDate(lastDay,lastMonth,year); } } else { var chineseBranch = (year-3)%12; var chineseStem = (year-3)%10; } if (chineseBranch == 0) chineseBranch = 12; if (chineseStem == 0) chineseStem = 10; chineseyearname = '(' + stems[chineseStem] + '-' + branches[chineseBranch] + ')'; return chinese[chineseBranch]; }
To retrieve the data the following JavaScript defines two global variables chineseyearrnage and chineseyearname which are populated by the Chinese() function:
var chineseyearrange = ''; var chineseyearname = ''; var chineseyear = Chinese(day,month,year); document.write('Chinese year of the ' + chineseyear + ' ' + chineseyearname + '
' + chineseyearrange);
Why not try it out the frame version yourself.
You can view the source code of the four components:
And now...The Weekly Update Script
Extending "Born of the 4th of July"
Monday's child is full of grace