dojo.provide("dojox.date.HebrewDate"); dojo.experimental("dojox.date.HebrewDate"); dojo.declare("dojox.date.HebrewDate", null, { // summary: The component defines the Hebrew Calendar Object // // description: // This module is similar to the Date() object provided by JavaScript // // example: // | dojo.require("dojox.date.HebrewDate"); // | // | var date = new dojox.date.HebrewDate(); // | document.writeln(date.getFullYear()+'\'+date.getMonth()+'\'+date.getDate()); TISHRI: 0, HESHVAN: 1, KISLEV: 2, TEVET: 3, SHEVAT: 4, ADAR_1: 5, ADAR: 6, NISAN: 7, IYAR: 8, SIVAN: 9, TAMUZ: 10, AV: 11, ELUL: 12, // Hebrew date calculations are performed in terms of days, hours, and // "parts" (or halakim), which are 1/1080 of an hour, or 3 1/3 seconds. _HOUR_PARTS: 1080, _DAY_PARTS: 24*1080, // An approximate value for the length of a lunar month. // It is used to calculate the approximate year and month of a given // absolute date. _MONTH_DAYS: 29, _MONTH_FRACT: 12*1080 + 793, _MONTH_PARTS: 29*24*1080 + 12*1080 + 793, // The time of the new moon (in parts) on 1 Tishri, year 1 (the epoch) // counting from noon on the day before. BAHARAD is an abbreviation of // Bet (Monday), Hey (5 hours from sunset), Resh-Daled (204). BAHARAD: 11*1080 + 204, // The Julian day of the Gregorian epoch, that is, January 1, 1 on the // Gregorian calendar. JAN_1_1_JULIAN_DAY: 1721426, /** * The lengths of the Hebrew months. This is complicated, because there * are three different types of years, or six if you count leap years. * Due to the rules for postponing the start of the year to avoid having * certain holidays fall on the sabbath, the year can end up being three * different lengths, called "deficient", "normal", and "complete". */ _MONTH_LENGTH: [ // Deficient Normal Complete [ 30, 30, 30 ], //Tishri [ 29, 29, 30 ], //Heshvan [ 29, 30, 30 ], //Kislev [ 29, 29, 29 ], //Tevet [ 30, 30, 30 ], //Shevat [ 30, 30, 30 ], //Adar I (leap years only) [ 29, 29, 29 ], //Adar [ 30, 30, 30 ], //Nisan [ 29, 29, 29 ], //Iyar [ 30, 30, 30 ], //Sivan [ 29, 29, 29 ], //Tammuz [ 30, 30, 30 ], //Av [ 29, 29, 29 ] //Elul ], /** * The cumulative # of days to the end of each month in a non-leap year * Although this can be calculated from the MONTH_LENGTH table, * keeping it around separately makes some calculations a lot faster */ _MONTH_START: [ // Deficient Normal Complete [ 0, 0, 0 ], // (placeholder) [ 30, 30, 30 ], // Tishri [ 59, 59, 60 ], // Heshvan [ 88, 89, 90 ], // Kislev [ 117, 118, 119 ], // Tevet [ 147, 148, 149 ], // Shevat [ 147, 148, 149 ], // (Adar I placeholder) [ 176, 177, 178 ], // Adar [ 206, 207, 208 ], // Nisan [ 235, 236, 237 ], // Iyar [ 265, 266, 267 ], // Sivan [ 294, 295, 296 ], // Tammuz [ 324, 325, 326 ], // Av [ 353, 354, 355 ] // Elul ], /** * The cumulative # of days to the end of each month in a leap year */ LEAP_MONTH_START: [ // Deficient Normal Complete [ 0, 0, 0 ], // (placeholder) [ 30, 30, 30 ], // Tishri [ 59, 59, 60 ], // Heshvan [ 88, 89, 90 ], // Kislev [ 117, 118, 119 ], // Tevet [ 147, 148, 149 ], // Shevat [ 177, 178, 179 ], // Adar I [ 206, 207, 208 ], // Adar II [ 236, 237, 238 ], // Nisan [ 265, 266, 267 ], // Iyar [ 295, 296, 297 ], // Sivan [ 324, 325, 326 ], // Tammuz [ 354, 355, 356 ], // Av [ 383, 384, 385 ] // Elul ], GREGORIAN_MONTH_COUNT: [ //len len2 st st2 [ 31, 31, 0, 0 ], // Jan [ 28, 29, 31, 31 ], // Feb [ 31, 31, 59, 60 ], // Mar [ 30, 30, 90, 91 ], // Apr [ 31, 31, 120, 121 ], // May [ 30, 30, 151, 152 ], // Jun [ 31, 31, 181, 182 ], // Jul [ 31, 31, 212, 213 ], // Aug [ 30, 30, 243, 244 ], // Sep [ 31, 31, 273, 274 ], // Oct [ 30, 30, 304, 305 ], // Nov [ 31, 31, 334, 335 ] // Dec // len length of month // len2 length of month in a leap year // st days in year before start of month // st2 days in year before month in leap year ], _date: 0, _month: 0, _year: 0, _hours: 0, _minutes: 0, _seconds: 0, _milliseconds: 0, _day: 0, constructor: function(){ // summary: This is the constructor // description: // This fucntion initialize the date object values // // example: // | var date1 = new dojox.date.HebrewDate(); // | // | var date2 = new dojox.date.HebrewDate(date1); // | // | var date3 = new dojox.date.HebrewDate(5768,2,12); var arg_no = arguments.length; if(arg_no==0){// use the current date value var date = new Date(); var result = this._computeHebrewFields(date); this._date = result[2]; this._month = result[1]; this._year = result[0]; this._hours = date.getHours(); this._minutes = date.getMinutes(); this._seconds = date.getSeconds(); this._milliseconds = date.getMilliseconds(); this._day = date.getDay(); }else if(arg_no ==1){ this._year = arguments[0].getFullYear(); this._month = arguments[0].getMonth(); this._date = arguments[0].getDate(); this._hours = arguments[0].getHours(); this._minutes = arguments[0].getMinutes(); this._seconds = arguments[0].getSeconds(); this._milliseconds = arguments[0].getMilliseconds(); }else if(arg_no >=3){ // YYYY MM DD arguments passed, month is from 0-12 this._year = parseInt(arguments[0]); this._month = parseInt(arguments[1]); this._date = parseInt(arguments[2]); if(!this.isLeapYear(this._year) && this._month>=5) {this._month++;} if(this._month >12 || (!this.isLeapYear(this._year) && this._month > 11)){ console.warn("the month is incorrect , set 0"); this._month = 0; } this._hours = (arguments[3]!=null )? parseInt(arguments[3]):0; this._minutes = (arguments[4]!=null )? parseInt(arguments[4]):0; this._seconds = (arguments[5]!=null )? parseInt(arguments[5]):0; this._milliseconds = (arguments[6]!=null )? parseInt(arguments[6]):0; } var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); }, getDate: function(){ // summary: This function returns the date value (1 - 30) // // example: // | var date1 = new dojox.date.HebrewDate(); // | // | document.writeln(date1.getDate); return parseInt(this._date); }, getMonth: function(){ // summary: This function return the month value ( 0 - 11 ) // // example: // | var date1 = new dojox.date.HebrewDate(); // | // | document.writeln(date1.getMonth()+1); return parseInt(this._month); }, getFullYear: function(){ // summary: This function return the Year value // // example: // | var date1 = new dojox.date.HebrewDate(); // | // | document.writeln(date1.getFullYear()); return parseInt(this._year); }, getHours: function(){ //summary: returns the Hour value return this._hours; }, getMinutes: function(){ //summary: returns the Minuites value return this._minutes; }, getSeconds: function(){ //summary: returns the seconde value return this._seconds; }, getMilliseconds: function(){ //summary: returns the Milliseconds value return this._milliseconds; }, setDate: function(/*number*/date){ // summary: This function sets the Date // example: // | var date1 = new dojox.date.HebrewDate(); // | date1.setDate(2); date = parseInt(date); if(date>0){ for(var mdays = this.getDaysInHebrewMonth(this._month, this._year); date > mdays; date -= mdays,mdays = this.getDaysInHebrewMonth(this._month, this._year)){ this._month ++; if(!this.isLeapYear(this._year)&&(this._month==5)) { this._month ++;} if(this._month >= 13){this._year++; this._month -= 13;} } this._date = date; }else{ for(mdays = this.getDaysInHebrewMonth((this._month-1)>=0 ? (this._month-1) : 12 ,((this._month-1)>=0)? this._year : this._year-1); date<=0; mdays = this.getDaysInHebrewMonth((this._month-1)>=0 ? (this._month-1) : 12,((this._month-1)>=0)? this._year : this._year-1) ){ this._month --; if(!this.isLeapYear(this._year) && this._month == 5){ this._month--; } if(this._month < 0){this._year--; this._month += 13;} date+=mdays; } this._date = date; } var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, setYear: function(/*number*/year){ // summary: This function set Year // // example: // | var date1 = new dojox.date.HebrewDate(); // | date1.setYear(5768); this._year = parseInt(year); if(!this.isLeapYear(this._year) && this._month==6){ this._month--; } var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, setMonth: function(/*number*/month){ // summary: This function set Month // // example: // | var date1 = new dojox.date.HebrewDate(); // | date1.setMonth(0); //first month var newMonth = parseInt(month); if(!this.isLeapYear(this._year) && newMonth > 5){newMonth ++;} if(newMonth>=0){ while (newMonth >12){ this._year++; newMonth -=13; if (!this.isLeapYear(this._year) && newMonth > 5) {newMonth ++;} } }else{ while (newMonth<0){ this._year--; newMonth +=13; if (!this.isLeapYear(this._year) && newMonth <= 5) {newMonth --;} } } this._month = newMonth; var dnum = this.getDaysInHebrewMonth(this._month, this._year); if(dnum < this._date){ this._date = dnum; } // if the date in this month more than number of the days in this month var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, setHours: function(){ //summary: set the Hours 0-23 var hours_arg_no = arguments.length; var hours = 0; if(hours_arg_no >= 1){ hours = parseInt(arguments[0]); } if(hours_arg_no >= 2){ this._minutes = parseInt(arguments[1]); } if(hours_arg_no >= 3){ this._seconds = parseInt(arguments[2]); } if(hours_arg_no == 4){ this._milliseconds = parseInt(arguments[3]); } while(hours >= 24){ this._date++; var mdays = this.getDaysInHebrewMonth(this._month, this._year); if(this._date > mdays) { this._month++; if(!this.isLeapYear(this._year)&&(this._month==5)){ this._month++; } if(this._month >= 13){this._year++; this._month -= 13;} this._date -= mdays; } hours -= 24; } this._hours = hours; var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, setMinutes: function(/*number*/minutes){ //summary: set the Minutes frm 0-59 while(minutes >= 60){ this._hours++; if(this._hours >= 24){ this._date++; this._hours -= 24; var mdays = this.getDaysInHebrewMonth(this._month, this._year); if(this._date > mdays){ this._month ++; if(!this.isLeapYear(this._year)&&(this._month==5)){ this._month++; } if(this._month >= 13){this._year++; this._month -= 13;} this._date -= mdays; } } minutes -= 60; } this._minutes = minutes; var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, setSeconds: function(/*number*/seconds){ //summary: set the Seconds from 0-59 while(seconds >= 60){ this._minutes++; if(this._minutes >= 60){ this._hours++; this._minutes -= 60; if(this._hours >= 24){ this._date++; this._hours -= 24; var mdays = this.getDaysInHebrewMonth(this._month, this._year); if(this._date > mdays){ this._month++; if(!this.isLeapYear(this._year)&&(this._month==5)){ this._month++; } if(this._month >= 13){this._year++; this._month -= 13;} this._date -= mdays; } } } seconds -= 60; } this._seconds = seconds; var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, setMilliseconds: function(/*number*/milliseconds){ //summary: set the setMilliseconds while(milliseconds >= 1000){ this.setSeconds++; if(this.setSeconds >= 60){ this._minutes++; this._seconds -= 60; if(this._minutes >= 60){ this._hours++; this._minutes -= 60; if(this._hours >= 24){ this._date++; this._hours -= 24; var mdays = this.getDaysInHebrewMonth(this._month, this._year); if(this._date > mdays) { this._month ++; if(!this.isLeapYear(this._year)&&(this._month==5)) this._month ++; if(this._month >= 13){this._year++; this._month -= 13;} this._date -= mdays; } } } } milliseconds -= 1000; } this._milliseconds = milliseconds; var day = this._startOfYear(this._year); if(this._month != 0){ if(this.isLeapYear(this._year)){ day += this.LEAP_MONTH_START[this._month][this._yearType(this._year)]; }else{ day += this._MONTH_START[this._month][this._yearType(this._year)]; } } day += (this._date - 1); this._day = ((day+1) % 7); return this; }, toString: function(){ // summary: This returns a string representation of the date in "dd, MM, YYYY HH:MM:SS" format // | // example: // | var date1 = new dojox.date.HebrewDate(); // | document.writeln(date1.toString()); return this._date + ", " + ((!this.isLeapYear(this._year) && this._month>5) ? this._month : (this._month+1)) + ", " + this._year + " " + this._hours + ":" + this._minutes + ":" + this._seconds; // String }, valueOf: function(){ return this.toGregorian().valueOf(); }, // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/ getDaysInHebrewMonth: function(/*number*/month, /*number*/ year){ // summary: returns the number of days in the month used switch(month){ case this.HESHVAN: case this.KISLEV: // These two month lengths can vary return this._MONTH_LENGTH[month][this._yearType(year)]; default: // The rest are a fixed length return this._MONTH_LENGTH[month][0]; } }, // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/ _yearType: function(/*number*/year){ var yearLength = this._handleGetYearLength(Number(year)); if(yearLength > 380){ yearLength -= 30; // Subtract length of leap month. } switch(yearLength){ case 353: return 0; case 354: return 1; case 355: return 2; } throw new Error("Illegal year length " + yearLength + " in year " + year); }, // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/ _handleGetYearLength: function(/*number*/eyear){ return this._startOfYear(eyear+1) - this._startOfYear(eyear); }, // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/ _startOfYear: function(/*number*/year){ var months = Math.floor((235 * year - 234) / 19); // # of months before year var frac = months * this._MONTH_FRACT + this.BAHARAD; // Fractional part of day # var day = months * 29 + Math.floor(frac / this._DAY_PARTS); // Whole # part of calculation frac %= this._DAY_PARTS; // Time of day var wd = day % 7; // Day of week (0 == Monday) if(wd == 2 || wd == 4 || wd == 6){ // If the 1st is on Sun, Wed, or Fri, postpone to the next day day += 1; wd = day % 7; } if(wd == 1 && frac > 15 * this._HOUR_PARTS + 204 && !this.isLeapYear(year)){ // If the new moon falls after 3:11:20am (15h204p from the previous noon) // on a Tuesday and it is not a leap year, postpone by 2 days. // This prevents 356-day years. day += 2; }else if(wd == 0 && frac > 21 * this._HOUR_PARTS + 589 && this.isLeapYear(year-1)){ // If the new moon falls after 9:32:43 1/3am (21h589p from yesterday noon) // on a Monday and *last* year was a leap year, postpone by 1 day. // Prevents 382-day years. day += 1; } return day; }, // ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/ isLeapYear: function(/*number*/year){ // summary: // Determines if the year (argument) is a leap year // description: The Leap year contains additional month adar sheni // //return (year * 12 + 17) % 19 >= 12; var x = (year*12 + 17) % 19; return x >= ((x < 0) ? -7 : 12); }, fromGregorian: function(/*Date*/gdate){ // summary: This function returns the equivalent Hebrew Date value for the Gregorian Date // example: // | var dateHebrew = new dojox.date.HebrewDate(); // | var dateGregorian = new Date(2008,10,12); // | dateHebrew.fromGregorian(dateGregorian); var result = this._computeHebrewFields(gdate); this._year = result[0]; this._month = result[1]; this._date = result[2]; this._hours = gdate.getHours(); this._milliseconds = gdate.getMilliseconds(); this._minutes = gdate.getMinutes(); this._seconds = gdate.getSeconds(); return this; }, // ported from the Java class com.ibm.icu.util.HebrewCalendar.handleComputeFields from ICU4J v3.6.1 at http://www.icu-project.org/ _computeHebrewFields: function(/*Date*/gdate){ var julianDay = this._getJulianDayFromGregorianDate(gdate); var d = julianDay - 347997; var m = Math.floor((d * this._DAY_PARTS) / this._MONTH_PARTS); // Months (approx) var year = Math.floor((19 * m + 234) / 235) + 1; // Years (approx) var ys = this._startOfYear(year); // 1st day of year var dayOfYear = (d - ys); // Because of the postponement rules, it's possible to guess wrong. Fix it. while(dayOfYear < 1){ year--; ys = this._startOfYear(year); dayOfYear = d - ys; } // Now figure out which month we're in, and the date within that month var typeofYear = this._yearType(year); var monthStart = this.isLeapYear(year) ? this.LEAP_MONTH_START : this._MONTH_START; var month = 0; while(dayOfYear > monthStart[month][typeofYear]){ month++; } month--; var dayOfMonth = dayOfYear - monthStart[month][typeofYear]; return [year, month, dayOfMonth]; }, // ported from the Java class com.ibm.icu.util.Calendar.computeGregorianFields from ICU4J v3.6.1 at http://www.icu-project.org/ toGregorian: function(){ // summary: This returns the equevalent Grogorian date value in Date object // example: // | var dateHebrew = new dojox.date.HebrewDate(5768,11,20); // | var dateGregorian = dateHebrew.toGregorian(); var hYear = this._year; var hMonth = this._month; var hDate = this._date; var day = this._startOfYear(hYear); if(hMonth != 0){ if(this.isLeapYear(hYear)){ day += this.LEAP_MONTH_START[hMonth][this._yearType(hYear)]; } else{ day += this._MONTH_START[hMonth][this._yearType(hYear)]; } } var julianDay = (hDate + day + 347997); // The Gregorian epoch day is zero for Monday January 1, year 1. var gregorianEpochDay = julianDay - this.JAN_1_1_JULIAN_DAY; // Here we convert from the day number to the multiple radix // representation. We use 400-year, 100-year, and 4-year cycles. // For example, the 4-year cycle has 4 years + 1 leap day; giving // 1461 == 365*4 + 1 days. var rem = new Array(1); var n400 = this._floorDivide(gregorianEpochDay , 146097, rem); // 400-year cycle length var n100 = this._floorDivide(rem[0] , 36524, rem); // 100-year cycle length var n4 = this._floorDivide(rem[0] , 1461, rem); // 4-year cycle length var n1 = this._floorDivide(rem[0] , 365, rem); var year = 400*n400 + 100*n100 + 4*n4 + n1; var dayOfYear = rem[0]; // zero-based day of year if(n100 == 4 || n1 == 4){ dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle }else{ ++year; } var isLeap = !(year%4) && // equiv. to (year%4 == 0) (year%100 || !(year%400)); var correction = 0; var march1 = isLeap ? 60 : 59; // zero-based DOY for March 1 if(dayOfYear >= march1){ correction = isLeap ? 1 : 2; } var month = Math.floor((12 * (dayOfYear + correction) + 6) / 367); // zero-based month var dayOfMonth = dayOfYear - this.GREGORIAN_MONTH_COUNT[month][isLeap?3:2] + 1; // one-based DOM return new Date(year, month, dayOfMonth, this._hours, this._minutes, this._seconds, this._milliseconds); }, _floorDivide: function(numerator, denominator, remainder){ if(numerator >= 0){ remainder[0] = (numerator % denominator); return Math.floor(numerator / denominator); } var quotient = Math.floor(numerator / denominator); remainder[0] = numerator - (quotient * denominator); return quotient; }, getDay: function(){ // summary: This function return Week Day value ( 0 - 6 ) // // example: // | var date1 = new dojox.date.HebrewDate(); // | // | document.writeln(date1.getDay()); var hYear = this._year; var hMonth = this._month; var hDate = this._date; var day = this._startOfYear(hYear); if(hMonth != 0){ if(this.isLeapYear(hYear)){ day += this.LEAP_MONTH_START[hMonth][this._yearType(hYear)]; } else{ day += this._MONTH_START[hMonth][this._yearType(hYear)]; } } day += hDate - 1; return (day+1) % 7; }, // ported from the Java class com.ibm.icu.util.Calendar.computeGregorianMonthStart from ICU4J v3.6.1 at http://www.icu-project.org/ _getJulianDayFromGregorianDate: function(gdate){ //summary: returns the Julian day of a Gregorian date var year = gdate.getFullYear(); var month = gdate.getMonth(); var d = gdate.getDate(); var isLeap = !(year%4) && (year%100 || !(year%400)); //TODO: dup var y = year - 1; // This computation is actually ... + (JAN_1_1_JULIAN_DAY - 3) + 2. // Add 2 because Gregorian calendar starts 2 days after Julian // calendar. var julianDay = 365*y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400) + this.JAN_1_1_JULIAN_DAY - 1; // At this point julianDay indicates the day BEFORE the first day // of January 1, of the Gregorian calendar. if(month != 0){ julianDay += this.GREGORIAN_MONTH_COUNT[month][isLeap?3:2]; } julianDay += d; return julianDay; } }); dojox.date.HebrewDate.fromGregorian = function(/*Date*/gdate){ // summary: This function returns the equivalent Hebrew Date value for the Gregorian Date // example: // | var dateGregorian = new Date(2008,10,12); // | var dateHebrew = dojox.date.HebrewDate.fromGregorian(dateGregorian); var dateHebrew = new dojox.date.HebrewDate(); return dateHebrew.fromGregorian(gdate); }; // Utility methods to do arithmetic calculations with HebrewDates dojox.date.HebrewDate.add = function(/*HebrewDate*/date, /*String*/interval, /*int*/amount){ // based on and similar to dojo.date.add // summary: // Add to a Date in intervals of different size, from milliseconds to years // date: HebrewDate // Date object to start with // interval: // A string representing the interval. One of the following: // "year", "month", "day", "hour", "minute", "second", // "millisecond", "week", "weekday" // amount: // How much to add to the date. var newHebrDate = new dojox.date.HebrewDate(date); switch(interval){ case "day": newHebrDate.setDate(date.getDate() + amount); break; case "weekday": var day = date.getDay(); if (((day + amount) < 5) && ((day + amount) >0)) { newHebrDate.setDate(date.getDate() + amount); }else{ var adddays = 0; /*weekend */ var remdays = 0; if (day == 5) {//friday day = 4; remdays = (amount > 0) ? -1 : 1; }else if (day == 6){ //shabat day = 4; remdays = (amount > 0) ? -2 : 2; } var add = (amount > 0) ? (5 - day - 1) : ( 0-day); var amountdif = amount - add; var div=parseInt(amountdif /5); if ((amountdif %5) != 0){ adddays = (amount > 0) ? 2 : -2; } adddays = adddays + div*7 + amountdif %5 + add; newHebrDate.setDate(date.getDate() + adddays + remdays); } break; case "year": newHebrDate.setYear(date.getFullYear() + amount ); break; case "week": amount *= 7; newHebrDate.setDate(date.getDate() + amount); break; case "month": var month = date.getMonth(); if(!date.isLeapYear(date.getFullYear()) && month > 5){month --;} newHebrDate.setMonth(month + amount ); break; case "hour": newHebrDate.setHours(date.getHours() + amount ); break; case "minute": newHebrDate.setMinutes(date.getMinutes() + amount ); break; case "second": newHebrDate.setSeconds(date.getSeconds() + amount ); break; case "millisecond": newHebrDate.setMilliseconds(date.getMilliseconds() + amount ); break; } return newHebrDate; // Date }; dojox.date.HebrewDate.difference = function(/*HebrewDate*/date1, /*HebrewDate?*/date2, /*String?*/interval){ // based on and similar to dojo.date.difference // summary: // date1 - date2 // date2 is HebrewDate object. If not specified, the current HebrewDate is used. // interval: // A string representing the interval. One of the following: // "year", "month", "day", "hour", "minute", "second", // "millisecond", "week", "weekday" // Defaults to "day". date2 = date2 || new dojox.date.HebrewDate(); interval = interval || "day"; var yearDiff = date1.getFullYear() - date2.getFullYear(); var delta = 1; // Integer return value switch(interval){ case "weekday": var days = Math.round(dojox.date.HebrewDate.difference(date1, date2, "day")); var weeks = parseInt(dojox.date.HebrewDate.difference(date1, date2, "week")); var mod = days % 7; // Even number of weeks if(mod == 0){ days = weeks*5; }else{ // Weeks plus spare change (< 7 days) var adj = 0; var aDay = date2.getDay(); var bDay = date1.getDay(); weeks = parseInt(days/7); mod = days % 7; // Mark the date advanced by the number of // round weeks (may be zero) var dtMark = new dojox.date.HebrewDate(date2); dtMark.setDate(dtMark.getDate()+(weeks*7)); var dayMark = dtMark.getDay(); // Spare change days -- 6 or less if(days > 0){ switch(true){ // Range starts on Fri case aDay == 5: adj = -1; break; // Range starts on Sat case aDay == 6: adj = 0; break; // Range ends on Fri case bDay == 5: adj = -1; break; // Range ends on Sat case bDay == 6: adj = -2; break; // Range contains weekend case (dayMark + mod) > 5: adj = -2; } }else if(days < 0){ switch(true){ // Range starts on Fri case aDay == 5: adj = 0; break; // Range starts on Sat case aDay == 6: adj = 1; break; // Range ends on Fri case bDay == 5: adj = 2; break; // Range ends on Sat case bDay == 6: adj = 1; break; // Range contains weekend case (dayMark + mod) < 0: adj = 2; } } days += adj; days -= (weeks*2); } delta = days; break; case "year": delta = yearDiff; break; case "month": var startdate = (date1.toGregorian() > date2.toGregorian()) ? date1 : date2; // more var enddate = (date1.toGregorian() > date2.toGregorian()) ? date2 : date1; var month1 = startdate.getMonth(); var month2 = enddate.getMonth(); if (yearDiff == 0){ delta = ( !date1.isLeapYear(date1.getFullYear()) && startdate.getMonth() > 5 && enddate.getMonth() <=5) ? (startdate.getMonth() - enddate.getMonth() - 1) : (startdate.getMonth() - enddate.getMonth() ); }else{ delta = (!enddate.isLeapYear(enddate.getFullYear()) && month2 < 6) ? (13-month2-1) : (13-month2); delta += (!startdate.isLeapYear(startdate.getFullYear()) && month1 > 5) ? (month1 -1): month1; var i = enddate.getFullYear() + 1; var e = startdate.getFullYear(); for (i; i < e; i++){ delta += enddate.isLeapYear(i) ? 13 : 12; } } if (date1.toGregorian() < date2.toGregorian()){ delta = -delta; } break; case "week": // Truncate instead of rounding // Don't use Math.floor -- value may be negative delta = parseInt(dojox.date.HebrewDate.difference(date1, date2, "day")/7); break; case "day": delta /= 24; // fallthrough case "hour": delta /= 60; // fallthrough case "minute": delta /= 60; // fallthrough case "second": delta /= 1000; // fallthrough case "millisecond": delta *= date1.toGregorian().getTime()- date2.toGregorian().getTime(); } // Round for fractional values and DST leaps return Math.round(delta); // Number (integer) };