Date.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. define("dojox/date/hebrew/Date", [
  2. "dojo/_base/kernel",
  3. "dojo/_base/declare",
  4. "./numerals"
  5. ], function(dojo, declare, numerals){
  6. dojo.getObject("date.hebrew.Date", true, dojox);
  7. dojo.experimental("dojox.date.hebrew.Date");
  8. dojo.declare("dojox.date.hebrew.Date", null, {
  9. // summary: A Date-like object which implements the Hebrew calendar
  10. //
  11. // description:
  12. // A Date-like object which implements the Hebrew Calendar. Because this object
  13. // implements many of the same methods as the native JavaScript Date object, which
  14. // implements the Gregorian calendar, it can often be used its place. Note that
  15. // this object does not extend Date or use its prototype.
  16. //
  17. // example:
  18. // | dojo.require("dojox.date.hebrew.Date");
  19. // |
  20. // | var date = new dojox.date.hebrew.Date();
  21. // | console.log(date.getFullYear()+'\'+date.getMonth()+'\'+date.getDate());
  22. // Hebrew date calculations are performed in terms of days, hours, and
  23. // "parts" (or halakim), which are 1/1080 of an hour, or 3 1/3 seconds.
  24. //_HOUR_PARTS: 1080,
  25. //_DAY_PARTS: 24*1080,
  26. // An approximate value for the length of a lunar month.
  27. // It is used to calculate the approximate year and month of a given
  28. // absolute date.
  29. //_MONTH_FRACT: 12*1080 + 793,
  30. //_MONTH_PARTS: 29*24*1080 + 12*1080 + 793,
  31. // The time of the new moon (in parts) on 1 Tishri, year 1 (the epoch)
  32. // counting from noon on the day before. BAHARAD is an abbreviation of
  33. // Bet (Monday), Hey (5 hours from sunset), Resh-Daled (204).
  34. //_BAHARAD: 11*1080 + 204,
  35. // The Julian day of the Gregorian epoch, that is, January 1, 1 on the
  36. // Gregorian calendar.
  37. //_JAN_1_1_JULIAN_DAY: 1721426,
  38. /**
  39. * The lengths of the Hebrew months. This is complicated, because there
  40. * are three different types of years, or six if you count leap years.
  41. * Due to the rules for postponing the start of the year to avoid having
  42. * certain holidays fall on the sabbath, the year can end up being three
  43. * different lengths, called "deficient", "normal", and "complete".
  44. */
  45. //"Absolute" indexes of months: Tishri - 0, Heshvan - 1, Kislev - 2, Tevet - 3, Shevat - 4, Adar I (leap years only) - 5, Adar - 6, Nisan - 7, Iyar - 8, Sivan - 9, Tammuz-10, Av - 11, Elul - 12.
  46. _MONTH_LENGTH: [
  47. // Deficient Normal Complete
  48. [ 30, 30, 30 ], //Tishri 0
  49. [ 29, 29, 30 ], //Heshvan 1
  50. [ 29, 30, 30 ], //Kislev 2
  51. [ 29, 29, 29 ], //Tevet 3
  52. [ 30, 30, 30 ], //Shevat 4
  53. [ 30, 30, 30 ], //Adar I (leap years only) 5
  54. [ 29, 29, 29 ], //Adar 6
  55. [ 30, 30, 30 ], //Nisan 7
  56. [ 29, 29, 29 ], //Iyar 8
  57. [ 30, 30, 30 ], //Sivan 9
  58. [ 29, 29, 29 ], //Tammuz 10
  59. [ 30, 30, 30 ], //Av 11
  60. [ 29, 29, 29 ] //Elul 12
  61. ],
  62. /**
  63. * The cumulative # of days to the end of each month in a non-leap year
  64. * Although this can be calculated from the MONTH_LENGTH table,
  65. * keeping it around separately makes some calculations a lot faster
  66. */
  67. _MONTH_START: [
  68. // Deficient Normal Complete
  69. [ 0, 0, 0 ], // (placeholder)
  70. [ 30, 30, 30 ], // Tishri
  71. [ 59, 59, 60 ], // Heshvan
  72. [ 88, 89, 90 ], // Kislev
  73. [ 117, 118, 119 ], // Tevet
  74. [ 147, 148, 149 ], // Shevat
  75. [ 147, 148, 149 ], // (Adar I placeholder)
  76. [ 176, 177, 178 ], // Adar
  77. [ 206, 207, 208 ], // Nisan
  78. [ 235, 236, 237 ], // Iyar
  79. [ 265, 266, 267 ], // Sivan
  80. [ 294, 295, 296 ], // Tammuz
  81. [ 324, 325, 326 ], // Av
  82. [ 353, 354, 355 ] // Elul
  83. ],
  84. /**
  85. * The cumulative # of days to the end of each month in a leap year
  86. */
  87. _LEAP_MONTH_START: [
  88. // Deficient Normal Complete
  89. [ 0, 0, 0 ], // (placeholder)
  90. [ 30, 30, 30 ], // Tishri
  91. [ 59, 59, 60 ], // Heshvan
  92. [ 88, 89, 90 ], // Kislev
  93. [ 117, 118, 119 ], // Tevet
  94. [ 147, 148, 149 ], // Shevat
  95. [ 177, 178, 179 ], // Adar I
  96. [ 206, 207, 208 ], // Adar II
  97. [ 236, 237, 238 ], // Nisan
  98. [ 265, 266, 267 ], // Iyar
  99. [ 295, 296, 297 ], // Sivan
  100. [ 324, 325, 326 ], // Tammuz
  101. [ 354, 355, 356 ], // Av
  102. [ 383, 384, 385 ] // Elul
  103. ],
  104. _GREGORIAN_MONTH_COUNT: [
  105. //len len2 st st2
  106. [ 31, 31, 0, 0 ], // Jan
  107. [ 28, 29, 31, 31 ], // Feb
  108. [ 31, 31, 59, 60 ], // Mar
  109. [ 30, 30, 90, 91 ], // Apr
  110. [ 31, 31, 120, 121 ], // May
  111. [ 30, 30, 151, 152 ], // Jun
  112. [ 31, 31, 181, 182 ], // Jul
  113. [ 31, 31, 212, 213 ], // Aug
  114. [ 30, 30, 243, 244 ], // Sep
  115. [ 31, 31, 273, 274 ], // Oct
  116. [ 30, 30, 304, 305 ], // Nov
  117. [ 31, 31, 334, 335 ] // Dec
  118. // len length of month
  119. // len2 length of month in a leap year
  120. // st days in year before start of month
  121. // st2 days in year before month in leap year
  122. ],
  123. _date: 0,
  124. _month: 0,
  125. _year: 0,
  126. _hours: 0,
  127. _minutes: 0,
  128. _seconds: 0,
  129. _milliseconds: 0,
  130. _day: 0,
  131. constructor: function(){
  132. // summary: initialize the date object value
  133. //
  134. // example:
  135. // | var date1 = new dojox.date.hebrew.Date();
  136. // |
  137. // | var date2 = new dojox.date.hebrew.Date(date1);
  138. // |
  139. // | var date3 = new dojox.date.hebrew.Date(5768,2,12);
  140. var len = arguments.length;
  141. if(!len){// use the current date value, added "" to the similarity to date
  142. this.fromGregorian(new Date());
  143. }else if(len == 1){
  144. var arg0 = arguments[0];
  145. if(typeof arg0 == "number"){ // this is time "valueof"
  146. arg0 = new Date(arg0);
  147. }
  148. if(arg0 instanceof Date){
  149. this.fromGregorian(arg0);
  150. }else if(arg0 == ""){
  151. // date should be invalid. Dijit relies on this behavior.
  152. this._year = this._month = this._date = this._hours = this._minutes = this._seconds = this._milliseconds = NaN;
  153. }else{ // this is hebrew.Date object
  154. this._year = arg0._year;
  155. this._month = arg0._month;
  156. this._date = arg0._date;
  157. this._hours = arg0._hours;
  158. this._minutes = arg0._minutes;
  159. this._seconds = arg0._seconds;
  160. this._milliseconds = arg0._milliseconds;
  161. }
  162. }else if(len >= 3){
  163. // YYYY, MM, DD arguments passed, month is from 0-12, "absolute" index of month
  164. this._year += arguments[0];
  165. this._month += arguments[1];
  166. this._date += arguments[2];
  167. if(this._month > 12){
  168. console.warn("the month is incorrect , set 0 " + this._month + " " + this._year );
  169. this._month = 0;
  170. }
  171. this._hours += arguments[3] || 0;
  172. this._minutes += arguments[4] || 0;
  173. this._seconds += arguments[5] || 0;
  174. this._milliseconds += arguments[6] || 0;
  175. }
  176. this._setDay();
  177. },
  178. getDate: function(){
  179. // summary: returns the date value (1 - 30)
  180. //
  181. // example:
  182. // | var date1 = new dojox.date.hebrew.Date();
  183. // |
  184. // | console.log(date1.getDate());
  185. return this._date; // int
  186. },
  187. getDateLocalized: function(/*String?*/locale){
  188. // summary: returns the date value as hebrew numerals for the Hebrew locale,
  189. // a number for all others.
  190. //
  191. // example:
  192. // | var date1 = new dojox.date.hebrew.Date();
  193. // |
  194. // | console.log(date1.getDate());
  195. return (locale || dojo.locale).match(/^he(?:-.+)?$/) ?
  196. numerals.getDayHebrewLetters(this._date) : this.getDate();
  197. },
  198. getMonth: function(){
  199. // summary: returns the month value (0 - 12)
  200. //
  201. // description: the result is the index in the month array:
  202. // 0. Tishri
  203. // 1. Heshvan
  204. // 2. Kislev
  205. // 3. Tevet
  206. // 4. Shevat
  207. // 5. Adar I (leap years only)
  208. // 6. Adar
  209. // 7. Nisan
  210. // 8. Iyar
  211. // 9. Sivan
  212. // 10. Tammuz
  213. // 11. Av
  214. // 12. Elul - 12
  215. // For non leap years, for months after Shevat, the actual position of
  216. // the month in the year (used for short format) is less than
  217. // the "absolute" index by 1.
  218. //
  219. // example:
  220. // | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
  221. // |
  222. // | console.log(date1.getMonth()+1);
  223. // | >> 7
  224. return this._month;
  225. },
  226. getFullYear: function(){
  227. // summary: returns the Year value
  228. //
  229. // example:
  230. // | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
  231. // |
  232. // | console.log(date1.getFullYear());
  233. // | >> 5769
  234. return this._year;
  235. },
  236. getHours: function(){
  237. //summary: returns the hour value
  238. return this._hours;
  239. },
  240. getMinutes: function(){
  241. //summary: returns the minutes value
  242. return this._minutes;
  243. },
  244. getSeconds: function(){
  245. //summary: returns the seconds value
  246. return this._seconds;
  247. },
  248. getMilliseconds: function(){
  249. //summary: returns the milliseconds value
  250. return this._milliseconds;
  251. },
  252. setDate: function(/*number*/date){
  253. // summary: sets the date number for a given month
  254. // example:
  255. // | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
  256. // | date1.setDate(2);
  257. date = +date;
  258. var mdays;
  259. if(date>0){
  260. while (date > (mdays = this.getDaysInHebrewMonth(this._month, this._year))){
  261. date -= mdays;
  262. this._month++;
  263. if(this._month >= 13){this._year++; this._month -= 13;}
  264. }
  265. }else{
  266. while(date<=0){
  267. mdays = this.getDaysInHebrewMonth((this._month-1)>=0 ? (this._month-1) : 12, ((this._month-1)>=0)? this._year : this._year-1);
  268. this._month--;
  269. if(this._month < 0){this._year--; this._month += 13;}
  270. date += mdays;
  271. }
  272. }
  273. this._date = date;
  274. this._setDay();
  275. return this;
  276. },
  277. setFullYear: function(/*number*/year, /*number?*/month, /*number?*/ date){
  278. // summary: set the year
  279. //
  280. // example:
  281. // | var date1 = new dojox.date.hebrew.Date();
  282. // | date1.setFullYear(5768);
  283. // | date1.setFullYear(5768, 1, 1);
  284. this._year = year = +year;
  285. if(!this.isLeapYear(year) && this._month==5){ //incorrect month number for non leap year
  286. this._month++;
  287. }
  288. if(month !== undefined){this.setMonth(month);}
  289. if(date !== undefined){this.setDate(date);}
  290. var dnum = this.getDaysInHebrewMonth(this._month, this._year);
  291. if(dnum < this._date){
  292. this._date = dnum;
  293. } // if the date in this month more than number of the days in this month
  294. this._setDay();
  295. return this;
  296. },
  297. setMonth: function(/*number*/month){
  298. // summary: sets the month. You should use "absolute" index in the month array:
  299. // 0. Tishri
  300. // 1. Heshvan
  301. // 2. Kislev
  302. // 3. Tevet
  303. // 4. Shevat
  304. // 5. Adar I (leap years only)
  305. // 6. Adar
  306. // 7. Nisan
  307. // 8. Iyar
  308. // 9. Sivan
  309. // 10. Tammuz
  310. // 11. Av
  311. // 12. Elul - 12
  312. // For non leap years, for months after Shevat, the actual position of
  313. // the month in the year (used for short format) is less than
  314. // the "absolute" index by 1.
  315. //
  316. // example:
  317. // | var date1 = new dojox.date.hebrew.Date();
  318. // | date1.setMonth(0); //first month
  319. month = +month; // coerce to a Number
  320. if(!this.isLeapYear(this._year) && month == 5){month++;}
  321. if(month>=0){
  322. while(month >12){
  323. this._year++;
  324. month -= 13;
  325. if (!this.isLeapYear(this._year) && month >= 5){month++;}
  326. }
  327. }else{
  328. while(month<0){
  329. this._year--;
  330. month += (!this.isLeapYear(this._year) && month < -7) ? 12 : 13;
  331. }
  332. }
  333. this._month = month;
  334. var dnum = this.getDaysInHebrewMonth(this._month, this._year);
  335. if(dnum < this._date){
  336. this._date = dnum;
  337. } // if the date in this month more than number of the days in this month
  338. this._setDay();
  339. return this;
  340. },
  341. setHours: function(){
  342. // summary: sets the hour
  343. //
  344. // description: Sets the hour and optionally minutes, seconds, milliseconds also.
  345. //
  346. // example:
  347. // | var date1 = new dojox.date.hebrew.Date();
  348. // | date1.setHours(12, 30, 0, 0);
  349. var hours_arg_no = arguments.length;
  350. var hours = 0;
  351. if(hours_arg_no >= 1){
  352. hours += +arguments[0];
  353. }
  354. if(hours_arg_no >= 2){
  355. this._minutes += +arguments[1];
  356. }
  357. if(hours_arg_no >= 3){
  358. this._seconds += +arguments[2];
  359. }
  360. if(hours_arg_no == 4){
  361. this._milliseconds += +arguments[3];
  362. }
  363. while(hours >= 24){
  364. this._date++;
  365. var mdays = this.getDaysInHebrewMonth(this._month, this._year);
  366. if(this._date > mdays)
  367. {
  368. this._month++;
  369. if(!this.isLeapYear(this._year) && this._month==5){ this._month++; }
  370. if(this._month >= 13){this._year++; this._month -= 13;}
  371. this._date -= mdays;
  372. }
  373. hours -= 24;
  374. }
  375. this._hours = hours;
  376. this._setDay();
  377. return this;
  378. },
  379. _addMinutes: function(/*Number*/minutes){
  380. minutes += this._minutes;
  381. this.setMinutes(minutes);
  382. this.setHours(this._hours + parseInt(minutes / 60));
  383. return this;
  384. },
  385. _addSeconds: function(/*Number*/seconds){
  386. seconds += this._seconds;
  387. this.setSeconds(seconds);
  388. this._addMinutes(parseInt(seconds / 60));
  389. return this;
  390. },
  391. _addMilliseconds: function(/*Number*/milliseconds){
  392. milliseconds += this._milliseconds;
  393. this.setMilliseconds(milliseconds);
  394. this._addSeconds(parseInt(milliseconds / 1000));
  395. return this;
  396. },
  397. setMinutes: function(/*Number*/minutes){
  398. //summary: sets the minutes (0-59) only.
  399. this._minutes = minutes % 60;
  400. return this;
  401. },
  402. setSeconds: function(/*Number*/seconds){
  403. //summary: sets the seconds (0-59) only.
  404. this._seconds = seconds % 60;
  405. return this;
  406. },
  407. setMilliseconds: function(/*Number*/milliseconds){
  408. this._milliseconds = milliseconds % 1000;
  409. return this;
  410. },
  411. _setDay: function(){
  412. var day = this._startOfYear(this._year);
  413. if(this._month != 0){
  414. day += (this.isLeapYear(this._year) ? this._LEAP_MONTH_START : this._MONTH_START)[this._month || 0][this._yearType(this._year)];
  415. }
  416. day += this._date - 1;
  417. this._day = (day+1) % 7;
  418. },
  419. toString: function(){
  420. // summary: returns a string representation of the date in "dd, MM, yyyy HH:mm:ss" format
  421. //
  422. // description: returns a string representation of the date in "dd, MM, yyyy HH:mm:ss" format (all numeric)
  423. // For user presentation, use dojox.date.hebrew.locale.format which will present in the appropriate language
  424. // and format. toString() language- and culturally-specific conventions to keep this module free of
  425. // dependencies on dojox.date.locale and dojo.cldr.
  426. //
  427. // example:
  428. // | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
  429. // | console.log(date1.toString());
  430. // | >>> "1, 6, 5769 0:0:0"
  431. return this._date + ", " + this._month + ", " + this._year + " " + this._hours + ":" + this._minutes + ":" + this._seconds; // String
  432. },
  433. // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
  434. getDaysInHebrewMonth: function(/*Number*/month, /*Number*/ year){
  435. // summary: returns the number of days in the given month and year
  436. // Aside from the leap month, these two months can vary: 1=HESHVAN, 2=KISLEV
  437. // The rest are a fixed length
  438. var yearType = (month == 1 || month == 2) ? this._yearType(year) : 0;
  439. return (!this.isLeapYear(this._year) && month == 5) ? 0 : this._MONTH_LENGTH[month][yearType];
  440. },
  441. // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
  442. _yearType: function(/*Number*/year){
  443. var yearLength = this._handleGetYearLength(Number(year));
  444. if(yearLength > 380){
  445. yearLength -= 30; // Subtract length of leap month.
  446. }
  447. var yearType = yearLength - 353;
  448. if (yearType < 0 || yearType > 2){
  449. throw new Error("Illegal year length " + yearLength + " in year " + year);
  450. }
  451. return yearType;
  452. },
  453. // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
  454. _handleGetYearLength: function(/*number*/eyear){
  455. return this._startOfYear(eyear+1) - this._startOfYear(eyear);
  456. },
  457. // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
  458. _startOfYear: function(/*number*/year){
  459. var months = Math.floor((235 * year - 234) / 19), // # of months before year
  460. frac = months * (12*1080 + 793) + 11*1080 + 204/*BAHARAD*/, // Fractional part of day #
  461. day = months * 29 + Math.floor(frac / (24*1080)); // Whole # part of calculation
  462. frac %= 24*1080; // Time of day
  463. var wd = day % 7; // Day of week (0 == Monday)
  464. if(wd == 2 || wd == 4 || wd == 6){
  465. // If the 1st is on Sun, Wed, or Fri, postpone to the next day
  466. day += 1;
  467. wd = day % 7;
  468. }
  469. if(wd == 1 && frac > 15 * 1080 + 204 && !this.isLeapYear(year)){
  470. // If the new moon falls after 3:11:20am (15h204p from the previous noon)
  471. // on a Tuesday and it is not a leap year, postpone by 2 days.
  472. // This prevents 356-day years.
  473. day += 2;
  474. }else if(wd == 0 && frac > 21 * 1080 + 589 && this.isLeapYear(year-1)){
  475. // If the new moon falls after 9:32:43 1/3am (21h589p from yesterday noon)
  476. // on a Monday and *last* year was a leap year, postpone by 1 day.
  477. // Prevents 382-day years.
  478. day += 1;
  479. }
  480. return day;
  481. },
  482. // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
  483. isLeapYear: function(/*Number*/year){
  484. // summary:
  485. // Determines if the year (argument) is a leap year
  486. // description: The Leap year contains additional month adar sheni
  487. //
  488. //return (year * 12 + 17) % 19 >= 12;
  489. var x = (year*12 + 17) % 19;
  490. return x >= ((x < 0) ? -7 : 12);
  491. },
  492. fromGregorian: function(/*Date*/gdate){
  493. // summary: This function sets this Date to the Hebrew Date corresponding to the Gregorian Date
  494. // example:
  495. // | var dateHebrew = new dojox.date.hebrew.Date();
  496. // | var dateGregorian = new Date(2008,10,12);
  497. // | dateHebrew.fromGregorian(dateGregorian);
  498. var result = (!isNaN(gdate)) ? this._computeHebrewFields(gdate) : NaN;
  499. this._year = (!isNaN(gdate)) ? result[0] : NaN;
  500. this._month = (!isNaN(gdate))? result[1] : NaN;
  501. this._date = (!isNaN(gdate)) ? result[2] : NaN;
  502. this._hours = gdate.getHours();
  503. this._milliseconds = gdate.getMilliseconds();
  504. this._minutes = gdate.getMinutes();
  505. this._seconds = gdate.getSeconds();
  506. if (!isNaN(gdate)) this._setDay();
  507. return this;
  508. },
  509. // ported from the Java class com.ibm.icu.util.HebrewCalendar.handleComputeFields from ICU4J v3.6.1 at http://www.icu-project.org/
  510. _computeHebrewFields: function(/*Date*/gdate){
  511. var julianDay = this._getJulianDayFromGregorianDate(gdate),
  512. d = julianDay - 347997,
  513. m = Math.floor((d * 24*1080) / (29*24*1080 + 12*1080 + 793)), // Months (approx)
  514. year = Math.floor((19 * m + 234) / 235) + 1, // Years (approx)
  515. ys = this._startOfYear(year), // 1st day of year
  516. dayOfYear = (d - ys);
  517. // Because of the postponement rules, it's possible to guess wrong. Fix it.
  518. while(dayOfYear < 1){
  519. year--;
  520. ys = this._startOfYear(year);
  521. dayOfYear = d - ys;
  522. }
  523. // Now figure out which month we're in, and the date within that month
  524. var typeofYear = this._yearType(year),
  525. monthStart = this.isLeapYear(year) ? this._LEAP_MONTH_START : this._MONTH_START,
  526. month = 0;
  527. while(dayOfYear > monthStart[month][typeofYear]){
  528. month++;
  529. }
  530. month--;
  531. var dayOfMonth = dayOfYear - monthStart[month][typeofYear];
  532. return [year, month, dayOfMonth];
  533. },
  534. // ported from the Java class com.ibm.icu.util.Calendar.computeGregorianFields from ICU4J v3.6.1 at http://www.icu-project.org/
  535. toGregorian: function(){
  536. // summary: returns the equivalent Grogorian date value as a native Date object
  537. // example:
  538. // | var dateHebrew = new dojox.date.hebrew.Date(5768,11,20);
  539. // | var dateGregorian = dateHebrew.toGregorian();
  540. var hYear = this._year || 0,
  541. hMonth = this._month || 0,
  542. hDate = this._date || 0,
  543. day = this._startOfYear(hYear);
  544. if(hMonth != 0){
  545. day += (this.isLeapYear(hYear) ? this._LEAP_MONTH_START : this._MONTH_START)[hMonth][this._yearType(hYear)];
  546. }
  547. var julianDay = (hDate + day + 347997),
  548. // The Gregorian epoch day is zero for Monday January 1, year 1.
  549. gregorianEpochDay = julianDay - 1721426;
  550. // Here we convert from the day number to the multiple radix
  551. // representation. We use 400-year, 100-year, and 4-year cycles.
  552. // For example, the 4-year cycle has 4 years + 1 leap day; giving
  553. // 1461 == 365*4 + 1 days.
  554. var rem = [];
  555. var n400 = this._floorDivide(gregorianEpochDay , 146097, rem), // 400-year cycle length
  556. n100 = this._floorDivide(rem[0] , 36524, rem), // 100-year cycle length
  557. n4 = this._floorDivide(rem[0] , 1461, rem), // 4-year cycle length
  558. n1 = this._floorDivide(rem[0] , 365, rem),
  559. year = 400*n400 + 100*n100 + 4*n4 + n1,
  560. dayOfYear = rem[0]; // zero-based day of year
  561. if(n100 == 4 || n1 == 4){
  562. dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
  563. }else{
  564. ++year;
  565. }
  566. var isLeap = !(year%4) && // equiv. to (year%4 == 0)
  567. (year%100 || !(year%400)),
  568. correction = 0,
  569. march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
  570. if(dayOfYear >= march1){ correction = isLeap ? 1 : 2; }
  571. var month = Math.floor((12 * (dayOfYear + correction) + 6) / 367); // zero-based month
  572. var dayOfMonth = dayOfYear -
  573. this._GREGORIAN_MONTH_COUNT[month][isLeap ? 3 : 2] + 1; // one-based DOM
  574. return new Date(year, month, dayOfMonth, this._hours, this._minutes, this._seconds, this._milliseconds); // Date
  575. },
  576. _floorDivide: function(numerator, denominator, remainder){
  577. if(numerator >= 0){
  578. remainder[0] = (numerator % denominator);
  579. return Math.floor(numerator / denominator);
  580. }
  581. var quotient = Math.floor(numerator / denominator);
  582. remainder[0] = numerator - (quotient * denominator);
  583. return quotient;
  584. },
  585. getDay: function(){
  586. // summary: returns weekday value (0 - 6)
  587. //
  588. // example:
  589. // | var date1 = new dojox.date.hebrew.Date();
  590. // |
  591. // | console.log(date1.getDay());
  592. var hYear = this._year,
  593. hMonth = this._month,
  594. hDate = this._date,
  595. day = this._startOfYear(hYear);
  596. if(hMonth != 0){
  597. day += (this.isLeapYear(hYear) ? this._LEAP_MONTH_START : this._MONTH_START)[hMonth][this._yearType(hYear)];
  598. }
  599. day += hDate - 1;
  600. return (day+1) % 7;
  601. },
  602. // ported from the Java class com.ibm.icu.util.Calendar.computeGregorianMonthStart from ICU4J v3.6.1 at http://www.icu-project.org/
  603. _getJulianDayFromGregorianDate: function(gdate){
  604. //summary: returns the Julian day of a Gregorian date
  605. var year = gdate.getFullYear(),
  606. month = gdate.getMonth(),
  607. d = gdate.getDate(),
  608. isLeap = !(year%4) && (year%100 || !(year%400)), //TODO: dup
  609. y = year - 1;
  610. // This computation is actually ... + (_JAN_1_1_JULIAN_DAY - 3) + 2.
  611. // Add 2 because Gregorian calendar starts 2 days after Julian
  612. // calendar.
  613. var julianDay = 365*y + Math.floor(y/4) - Math.floor(y/100) +
  614. Math.floor(y/400) + 1721426 - 1;
  615. // At this point julianDay indicates the day BEFORE the first day
  616. // of January 1, <eyear> of the Gregorian calendar.
  617. if(month > 0) {
  618. julianDay += this._GREGORIAN_MONTH_COUNT[month][isLeap ? 3 : 2];
  619. }
  620. julianDay += d;
  621. return julianDay;
  622. }
  623. });
  624. dojox.date.hebrew.Date.prototype.valueOf = function(){
  625. return this.toGregorian().valueOf();
  626. };
  627. return dojox.date.hebrew.Date;
  628. });