hebrewCalendar.js 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. define(
  2. [ "../impl/Record", "../impl/calendarFunctions" ], function (Record, calendarFunctions) {
  3. // A helek ( plural halakim ) is the basic unit of time measurement in the Hebrew calendar.
  4. // There are exactly 1080 halakim in an hour. Ref: http://en.wikipedia.org/wiki/Helek
  5. var HALAKIM_PER_HOUR = 1080;
  6. var HALAKIM_PER_DAY = 24 * HALAKIM_PER_HOUR;
  7. var HALAKIM_FRACTIONAL_MONTH = 12 * HALAKIM_PER_HOUR + 793;
  8. var HALAKIM_PER_MONTH = 29 * HALAKIM_PER_DAY + HALAKIM_FRACTIONAL_MONTH; // Refers to a Hebrew mean month.
  9. // BAHARAD refers to the time of the new moon (in halakim) on 1 Tishri, year 1 (the epoch)
  10. // counting from noon on the day before.
  11. var BAHARAD = 11 * HALAKIM_PER_HOUR + 204;
  12. var MILLIS_PER_MINUTE = 60000;
  13. function isLeapYear(year) {
  14. var x = (year * 12 + 17) % 19;
  15. return x >= ((x < 0) ? -7 : 12);
  16. }
  17. function firstDayOfYear(year) {
  18. var monthsBeforeYear = Math.floor((235 * year - 234) / 19);
  19. var fractionalMonthsBeforeYear = monthsBeforeYear * HALAKIM_FRACTIONAL_MONTH + BAHARAD;
  20. var dayNumber = monthsBeforeYear * 29 + Math.floor(fractionalMonthsBeforeYear / HALAKIM_PER_DAY);
  21. var timeOfDay = fractionalMonthsBeforeYear % HALAKIM_PER_DAY;
  22. var dayOfWeek = dayNumber % 7; // 0 == Monday
  23. // Postponement rules.
  24. if (dayOfWeek === 2 || dayOfWeek === 4 || dayOfWeek === 6) {
  25. dayNumber++;
  26. dayOfWeek = dayNumber % 7;
  27. }
  28. if (dayOfWeek === 1 && timeOfDay > 15 * HALAKIM_PER_HOUR + 204 && !isLeapYear(year)) {
  29. dayNumber += 2;
  30. } else if (dayOfWeek === 0 && timeOfDay > 21 * HALAKIM_PER_HOUR + 589 && isLeapYear(year - 1)) {
  31. dayNumber++;
  32. }
  33. return dayNumber;
  34. }
  35. var calendarHebrew = {
  36. isLeapYear : isLeapYear,
  37. toLocalTime : function (date, timeZone) {
  38. var result = new Record();
  39. var dt = new Date(date);
  40. result.set("weekday", timeZone === "UTC" ? dt.getUTCDay() : dt.getDay());
  41. result.set("era", 0);
  42. var MILLIS_PER_DAY = 86400000;
  43. var HEBREW_DAY_ON_JAN_1_1970 = 2092591;
  44. var time = timeZone === "UTC" ? dt.getTime() : dt.getTime() - dt.getTimezoneOffset() * MILLIS_PER_MINUTE;
  45. var daysSinceEpoch = Math.floor(time / MILLIS_PER_DAY) + HEBREW_DAY_ON_JAN_1_1970;
  46. var monthsSinceEpoch = Math.floor(daysSinceEpoch * HALAKIM_PER_DAY / HALAKIM_PER_MONTH);
  47. var year = Math.floor((monthsSinceEpoch * 19 + 234) / 235) + 1;
  48. var firstDayOfThisYear = firstDayOfYear(year);
  49. var dayOfYear = daysSinceEpoch - firstDayOfThisYear;
  50. while (dayOfYear < 1) {
  51. year--;
  52. firstDayOfThisYear = firstDayOfYear(year);
  53. dayOfYear = daysSinceEpoch - firstDayOfThisYear;
  54. }
  55. var yearLength = firstDayOfYear(year + 1) - firstDayOfThisYear;
  56. if (yearLength > 380) {
  57. yearLength -= 30;
  58. }
  59. var yearType = yearLength - 353; // This should result in 0 = deficient, 1 = normal, 2 = complete
  60. var leapYear = isLeapYear(year);
  61. var daysInMonth = leapYear ?
  62. [ 30, 29, 29, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ] :
  63. [ 30, 29, 29, 29, 30, 29, 30, 29, 30, 29, 30, 29 ];
  64. if (yearType > 0) {
  65. daysInMonth[2]++; // Kislev gets an extra day in normal or complete years.
  66. }
  67. if (yearType > 1) {
  68. daysInMonth[1]++; // Heshvan gets an extra day in complete years only.
  69. }
  70. var month = 0;
  71. var day = dayOfYear;
  72. while (day > daysInMonth[month]) {
  73. day -= daysInMonth[month];
  74. month++;
  75. }
  76. result.set("year", year);
  77. result.set("month", month);
  78. result.set("day", day);
  79. calendarFunctions.setTimeFields(dt, timeZone, result);
  80. return result;
  81. }
  82. };
  83. return calendarHebrew;
  84. });