source: [view]
dojo.provide("dojox.date.hebrew.Date");
dojo.require("dojox.date.hebrew.numerals");
dojo.declare("dojox.date.hebrew.Date", null, {
// summary: A Date-like object which implements the Hebrew calendar
//
// description:
// A Date-like object which implements the Hebrew Calendar. Because this object
// implements many of the same methods as the native JavaScript Date object, which
// implements the Gregorian calendar, it can often be used its place. Note that
// this object does not extend Date or use its prototype.
//
// example:
// | dojo.require("dojox.date.hebrew.Date");
// |
// | var date = new dojox.date.hebrew.Date();
// | console.log(date.getFullYear()+'\'+date.getMonth()+'\'+date.getDate());
// 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_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".
*/
//"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.
_MONTH_LENGTH: [
// Deficient Normal Complete
[ 30, 30, 30 ], //Tishri 0
[ 29, 29, 30 ], //Heshvan 1
[ 29, 30, 30 ], //Kislev 2
[ 29, 29, 29 ], //Tevet 3
[ 30, 30, 30 ], //Shevat 4
[ 30, 30, 30 ], //Adar I (leap years only) 5
[ 29, 29, 29 ], //Adar 6
[ 30, 30, 30 ], //Nisan 7
[ 29, 29, 29 ], //Iyar 8
[ 30, 30, 30 ], //Sivan 9
[ 29, 29, 29 ], //Tammuz 10
[ 30, 30, 30 ], //Av 11
[ 29, 29, 29 ] //Elul 12
],
/**
* 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: initialize the date object value
//
// example:
// | var date1 = new dojox.date.hebrew.Date();
// |
// | var date2 = new dojox.date.hebrew.Date(date1);
// |
// | var date3 = new dojox.date.hebrew.Date(5768,2,12);
var len = arguments.length;
if(!len){// use the current date value, added "" to the similarity to date
this.fromGregorian(new Date());
}else if(len == 1){
var arg0 = arguments[0];
if(typeof arg0 == "number"){ // this is time "valueof"
arg0 = new Date(arg0);
}
if(arg0 instanceof Date){
this.fromGregorian(arg0);
}else if(arg0 == ""){
// date should be invalid. Dijit relies on this behavior.
this._date = new Date(""); //TODO: should this be NaN? _date is not a Date object
}else{ // this is hebrew.Date object
this._year = arg0._year;
this._month = arg0._month;
this._date = arg0._date;
this._hours = arg0._hours;
this._minutes = arg0._minutes;
this._seconds = arg0._seconds;
this._milliseconds = arg0._milliseconds;
}
}else if(len >= 3){
// YYYY, MM, DD arguments passed, month is from 0-12, "absolute" index of month
this._year += arguments[0];
this._month += arguments[1];
this._date += arguments[2];
if(this._month > 12){
console.warn("the month is incorrect , set 0 " + this._month + " " + this._year );
this._month = 0;
}
this._hours += arguments[3] || 0;
this._minutes += arguments[4] || 0;
this._seconds += arguments[5] || 0;
this._milliseconds += arguments[6] || 0;
}
this._setDay();
},
getDate: function(){
// summary: returns the date value (1 - 30)
//
// example:
// | var date1 = new dojox.date.hebrew.Date();
// |
// | console.log(date1.getDate());
return this._date; // int
},
getDateLocalized: function(/*String?*/locale){
// summary: returns the date value as hebrew numerals for the Hebrew locale,
// a number for all others.
//
// example:
// | var date1 = new dojox.date.hebrew.Date();
// |
// | console.log(date1.getDate());
return (locale || dojo.locale).match(/^he(?:-.+)?$/) ?
dojox.date.hebrew.numerals.getDayHebrewLetters(this._date) : this.getDate();
},
getMonth: function(){
// summary: returns the month value (0 - 12)
//
// description: the result is the index in the month array:
// 0. Tishri
// 1. Heshvan
// 2. Kislev
// 3. Tevet
// 4. Shevat
// 5. Adar I (leap years only)
// 6. Adar
// 7. Nisan
// 8. Iyar
// 9. Sivan
// 10. Tammuz
// 11. Av
// 12. Elul - 12
// For non leap years, for months after Shevat, the actual position of
// the month in the year (used for short format) is less than
// the "absolute" index by 1.
//
// example:
// | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
// |
// | console.log(date1.getMonth()+1);
// | >> 7
return this._month;
},
getFullYear: function(){
// summary: returns the Year value
//
// example:
// | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
// |
// | console.log(date1.getFullYear());
// | >> 5769
return this._year;
},
getHours: function(){
//summary: returns the hour value
return this._hours;
},
getMinutes: function(){
//summary: returns the minutes value
return this._minutes;
},
getSeconds: function(){
//summary: returns the seconds value
return this._seconds;
},
getMilliseconds: function(){
//summary: returns the milliseconds value
return this._milliseconds;
},
setDate: function(/*number*/date){
// summary: sets the date number for a given month
// example:
// | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
// | date1.setDate(2);
date = +date;
var mdays;
if(date>0){
while (date > (mdays = this.getDaysInHebrewMonth(this._month, this._year))){
date -= mdays;
this._month++;
if(this._month >= 13){this._year++; this._month -= 13;}
}
}else{
while(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._month < 0){this._year--; this._month += 13;}
date += mdays;
}
}
this._date = date;
this._setDay();
return this;
},
setFullYear: function(/*number*/year, /*number?*/month, /*number?*/ date){
// summary: set the year
//
// example:
// | var date1 = new dojox.date.hebrew.Date();
// | date1.setFullYear(5768);
// | date1.setFullYear(5768, 1, 1);
this._year = year = +year;
if(!this.isLeapYear(year) && this._month==5){ //incorrect month number for non leap year
this._month++;
}
if(month !== undefined){this.setMonth(month);}
if(date !== undefined){this.setDate(date);}
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
this._setDay();
return this;
},
setMonth: function(/*number*/month){
// summary: sets the month. You should use "absolute" index in the month array:
// 0. Tishri
// 1. Heshvan
// 2. Kislev
// 3. Tevet
// 4. Shevat
// 5. Adar I (leap years only)
// 6. Adar
// 7. Nisan
// 8. Iyar
// 9. Sivan
// 10. Tammuz
// 11. Av
// 12. Elul - 12
// For non leap years, for months after Shevat, the actual position of
// the month in the year (used for short format) is less than
// the "absolute" index by 1.
//
// example:
// | var date1 = new dojox.date.hebrew.Date();
// | date1.setMonth(0); //first month
month = +month; // coerce to a Number
if(!this.isLeapYear(this._year) && month == 5){month++;}
if(month>=0){
while(month >12){
this._year++;
month -= 13;
if (!this.isLeapYear(this._year) && month >= 5){month++;}
}
}else{
while(month<0){
this._year--;
month += (!this.isLeapYear(this._year) && month < -7) ? 12 : 13;
}
}
this._month = month;
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
this._setDay();
return this;
},
setHours: function(){
// summary: sets the hour
//
// description: Sets the hour and optionally minutes, seconds, milliseconds also.
//
// example:
// | var date1 = new dojox.date.hebrew.Date();
// | date1.setHours(12, 30, 0, 0);
var hours_arg_no = arguments.length;
var hours = 0;
if(hours_arg_no >= 1){
hours += +arguments[0];
}
if(hours_arg_no >= 2){
this._minutes += +arguments[1];
}
if(hours_arg_no >= 3){
this._seconds += +arguments[2];
}
if(hours_arg_no == 4){
this._milliseconds += +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;
this._setDay();
return this;
},
setMinutes: function(/*Number*/minutes){
//summary: sets the minutes (0-59)
minutes = +minutes;
this._minutes = minutes % 60;
this.setHours(parseInt(minutes / 60));
this._setDay();
return this;
},
setSeconds: function(/*Number*/seconds){
//summary: sets the seconds (0-59)
seconds = +seconds;
this._seconds = seconds % 60;
this.setMinutes(parseInt(seconds / 60));
this._setDay();
return this;
},
setMilliseconds: function(/*Number*/milliseconds){
//summary: sets the milliseconds
milliseconds = +milliseconds;
this._milliseconds = milliseconds % 1000;
this.setSeconds(parseInt(milliseconds / 1000));
this._setDay();
return this;
},
_setDay: function(){
var day = this._startOfYear(this._year);
if(this._month != 0){
day += (this.isLeapYear(this._year) ? this._LEAP_MONTH_START : this._MONTH_START)[this._month][this._yearType(this._year)];
}
day += this._date - 1;
this._day = (day+1) % 7;
},
toString: function(){
// summary: returns a string representation of the date in "dd, MM, yyyy HH:mm:ss" format
//
// description: returns a string representation of the date in "dd, MM, yyyy HH:mm:ss" format (all numeric)
// For user presentation, use dojox.date.hebrew.locale.format which will present in the appropriate language
// and format. toString() language- and culturally-specific conventions to keep this module free of
// dependencies on dojox.date.locale and dojo.cldr.
//
// example:
// | var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
// | console.log(date1.toString());
// | >>> "1, 6, 5769 0:0:0"
return this._date + ", " + this._month + ", " + this._year + " " + this._hours + ":" + this._minutes + ":" + this._seconds; // String
},
// 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 given month and year
// Aside from the leap month, these two months can vary: 1=HESHVAN, 2=KISLEV
// The rest are a fixed length
var yearType = (month == 1 || month == 2) ? this._yearType(year) : 0;
return (!this.isLeapYear(this._year) && month == 5) ? 0 : this._MONTH_LENGTH[month][yearType];