547 lines
15 KiB
JavaScript
547 lines
15 KiB
JavaScript
|
dojo.provide("dojox.date.IslamicDate");
|
||
|
dojo.experimental("dojox.date.IslamicDate");
|
||
|
|
||
|
dojo.require("dojo.date.locale"); //TODO: move dependency to another module?
|
||
|
dojo.require("dojo.date");
|
||
|
dojo.requireLocalization("dojo.cldr", "islamic");
|
||
|
|
||
|
dojo.declare("dojox.date.IslamicDate", null, {
|
||
|
// summary: The component defines the Islamic (Hijri) Calendar Object
|
||
|
//
|
||
|
// description:
|
||
|
// This module is similar to the Date() object provided by JavaScript
|
||
|
//
|
||
|
// example:
|
||
|
// | dojo.require("dojox.date.IslamicDate");
|
||
|
// |
|
||
|
// | var date = new dojox.date.IslamicDate();
|
||
|
// | document.writeln(date.getFullYear()+'\'+date.getMonth()+'\'+date.getDate());
|
||
|
|
||
|
|
||
|
_date: 0,
|
||
|
_month: 0,
|
||
|
_year: 0,
|
||
|
_hours: 0,
|
||
|
_minutes: 0,
|
||
|
_seconds: 0,
|
||
|
_milliseconds: 0,
|
||
|
_day: 0,
|
||
|
_GREGORIAN_EPOCH : 1721425.5,
|
||
|
_ISLAMIC_EPOCH : 1948439.5,
|
||
|
|
||
|
constructor: function(){
|
||
|
// summary: This is the constructor
|
||
|
// description:
|
||
|
// This fucntion initialize the date object values
|
||
|
//
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// |
|
||
|
// | var date2 = new dojox.date.IslamicDate("12\2\1429");
|
||
|
// |
|
||
|
// | var date3 = new dojox.date.IslamicDate(date2);
|
||
|
// |
|
||
|
// | var date4 = new dojox.date.IslamicDate(1429,2,12);
|
||
|
|
||
|
var arg_no = arguments.length;
|
||
|
|
||
|
if(arg_no == 0){
|
||
|
// use the current date value
|
||
|
var d = new Date();
|
||
|
this._day = d.getDay();
|
||
|
this.fromGregorian(d);
|
||
|
}else if(arg_no ==1){
|
||
|
//date string or Islamic date object passed
|
||
|
this.parse(arguments[0]);
|
||
|
}else if(arg_no >=3){
|
||
|
// YYYY MM DD arguments passed
|
||
|
this._year = arguments[0];
|
||
|
this._month = arguments[1];
|
||
|
this._date = arguments[2];
|
||
|
this._hours = arguments[3] || 0;
|
||
|
this._minutes = arguments[4] || 0;
|
||
|
this._seconds = arguments[5] || 0;
|
||
|
this._milliseconds = arguments[6] || 0;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getDate:function(){
|
||
|
// summary: This function returns the date value (1 - 30)
|
||
|
//
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// |
|
||
|
// | 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.IslamicDate();
|
||
|
// |
|
||
|
// | document.writeln(date1.getMonth()+1);
|
||
|
|
||
|
return parseInt(this._month);
|
||
|
},
|
||
|
|
||
|
getFullYear:function(){
|
||
|
// summary: This function return the Year value
|
||
|
//
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// |
|
||
|
// | document.writeln(date1.getFullYear());
|
||
|
|
||
|
return parseInt(this._year);
|
||
|
},
|
||
|
|
||
|
getDay:function(){
|
||
|
// summary: This function return Week Day value ( 0 - 6 )
|
||
|
//
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// |
|
||
|
// | document.writeln(date1.getDay());
|
||
|
|
||
|
var gd = this.toGregorian();
|
||
|
return gd.getDay();
|
||
|
},
|
||
|
|
||
|
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.IslamicDate();
|
||
|
// | date1.setDate(2);
|
||
|
|
||
|
date = parseInt(date);
|
||
|
|
||
|
if(date > 0 && date <= this.getDaysInIslamicMonth(this._month, this._year)){
|
||
|
this._date = date;
|
||
|
}else{
|
||
|
var mdays;
|
||
|
if(date>0){
|
||
|
for(mdays = this.getDaysInIslamicMonth(this._month, this._year);
|
||
|
date > mdays;
|
||
|
date -= mdays,mdays =this.getDaysInIslamicMonth(this._month, this._year)){
|
||
|
this._month++;
|
||
|
if(this._month >= 12){this._year++; this._month -= 12;}
|
||
|
}
|
||
|
|
||
|
this._date = date;
|
||
|
}else{
|
||
|
for(mdays = this.getDaysInIslamicMonth((this._month-1)>=0 ?(this._month-1) :11 ,((this._month-1)>=0)? this._year: this._year-1);
|
||
|
date <= 0;
|
||
|
mdays = this.getDaysInIslamicMonth((this._month-1)>=0 ? (this._month-1) :11,((this._month-1)>=0)? this._year: this._year-1)){
|
||
|
this._month--;
|
||
|
if(this._month < 0){this._year--; this._month += 12;}
|
||
|
|
||
|
date+=mdays;
|
||
|
}
|
||
|
this._date = date;
|
||
|
}
|
||
|
}
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
setYear:function(/*number*/year){
|
||
|
// summary: This function set Year
|
||
|
//
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// | date1.setYear(1429);
|
||
|
|
||
|
this._year = parseInt(year);
|
||
|
},
|
||
|
|
||
|
|
||
|
setMonth:function(/*number*/month){
|
||
|
// summary: This function set Month
|
||
|
//
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// | date1.setMonth(2);
|
||
|
|
||
|
this._year += Math.floor(month / 12);
|
||
|
this._month = Math.floor(month % 12);
|
||
|
},
|
||
|
|
||
|
setHours:function(){
|
||
|
//summary: set the Hours
|
||
|
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.getDaysInIslamicMonth(this._month, this._year);
|
||
|
if(this._date > mdays){
|
||
|
this._month ++;
|
||
|
if(this._month >= 12){this._year++; this._month -= 12;}
|
||
|
this._date -= mdays;
|
||
|
}
|
||
|
hours -= 24;
|
||
|
}
|
||
|
this._hours = hours;
|
||
|
},
|
||
|
|
||
|
setMinutes:function(/*number*/minutes){
|
||
|
//summary: set the Minutes
|
||
|
|
||
|
while(minutes >= 60){
|
||
|
this._hours++;
|
||
|
if(this._hours >= 24){
|
||
|
this._date++;
|
||
|
this._hours -= 24;
|
||
|
var mdays = this.getDaysInIslamicMonth(this._month, this._year);
|
||
|
if(this._date > mdays){
|
||
|
this._month ++;
|
||
|
if(this._month >= 12){this._year++; this._month -= 12;}
|
||
|
this._date -= mdays;
|
||
|
}
|
||
|
}
|
||
|
minutes -= 60;
|
||
|
}
|
||
|
this._minutes = minutes;
|
||
|
},
|
||
|
|
||
|
|
||
|
setSeconds:function(/*number*/seconds){
|
||
|
//summary: set Seconds
|
||
|
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.getDaysInIslamicMonth(this._month, this._year);
|
||
|
if(this._date > mdays){
|
||
|
this._month ++;
|
||
|
if(this._month >= 12){this._year++; this._month -= 12;}
|
||
|
this._date -= mdays;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
seconds -= 60;
|
||
|
}
|
||
|
this._seconds = seconds;
|
||
|
},
|
||
|
|
||
|
setMilliseconds:function(/*number*/milliseconds){
|
||
|
//summary: set the Millisconds
|
||
|
while(milliseconds >= 1000){
|
||
|
this.setSeconds++;
|
||
|
if(this.setSeconds >= 60){
|
||
|
this._minutes++;
|
||
|
this.setSeconds -= 60;
|
||
|
if(this._minutes >= 60){
|
||
|
this._hours++;
|
||
|
this._minutes -= 60;
|
||
|
if(this._hours >= 24){
|
||
|
this._date++;
|
||
|
this._hours -= 24;
|
||
|
var mdays = this.getDaysInIslamicMonth(this._month, this._year);
|
||
|
if(this._date > mdays){
|
||
|
this._month ++;
|
||
|
if(this._month >= 12){this._year++; this._month -= 12;}
|
||
|
this._date -= mdays;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
milliseconds -= 1000;
|
||
|
}
|
||
|
this._milliseconds = milliseconds;
|
||
|
},
|
||
|
|
||
|
|
||
|
toString:function(){
|
||
|
// summary: This returns a string representation of the date in "DDDD MMMM DD YYYY HH:MM:SS" format
|
||
|
// example:
|
||
|
// | var date1 = new dojox.date.IslamicDate();
|
||
|
// | document.writeln(date1.toString());
|
||
|
|
||
|
//FIXME: TZ/DST issues?
|
||
|
var x = new Date();
|
||
|
x.setHours(this._hours);
|
||
|
x.setMinutes(this._minutes);
|
||
|
x.setSeconds(this._seconds);
|
||
|
x.setMilliseconds(this._milliseconds);
|
||
|
var timeString = x.toTimeString();
|
||
|
//TODO : needs to be internationalized using dojo.date.format()? or use separate module
|
||
|
return(dojox.date.IslamicDate.weekDays[this.getDay()] +" "+dojox.date.IslamicDate.months[this._month]+" "+ this._date + " " + this._year+" "+timeString);
|
||
|
},
|
||
|
|
||
|
|
||
|
toGregorian:function(){
|
||
|
// summary: This returns the equevalent Grogorian date value in Date object
|
||
|
// example:
|
||
|
// | var dateIslamic = new dojox.date.IslamicDate(1429,11,20);
|
||
|
// | var dateGregorian = dateIslamic.toGregorian();
|
||
|
|
||
|
var hYear = this._year;
|
||
|
var hMonth = this._month;
|
||
|
var hDate = this._date;
|
||
|
var julianDay = hDate + Math.ceil(29.5 * hMonth) + (hYear - 1) * 354
|
||
|
+ Math.floor((3 + (11 * hYear)) / 30) + this._ISLAMIC_EPOCH - 1;
|
||
|
|
||
|
var wjd = Math.floor(julianDay - 0.5) + 0.5,
|
||
|
depoch = wjd - this._GREGORIAN_EPOCH,
|
||
|
quadricent = Math.floor(depoch / 146097),
|
||
|
dqc = this._mod(depoch, 146097),
|
||
|
cent = Math.floor(dqc / 36524),
|
||
|
dcent = this._mod(dqc, 36524),
|
||
|
quad = Math.floor(dcent / 1461),
|
||
|
dquad = this._mod(dcent, 1461),
|
||
|
yindex = Math.floor(dquad / 365),
|
||
|
year = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex;
|
||
|
if(!(cent == 4 || yindex == 4)){
|
||
|
year++;
|
||
|
}
|
||
|
|
||
|
var gYearStart = this._GREGORIAN_EPOCH + (365 * (year - 1)) + Math.floor((year - 1) / 4)
|
||
|
- ( Math.floor((year - 1) / 100)) + Math.floor((year - 1) / 400);
|
||
|
|
||
|
var yearday = wjd - gYearStart;
|
||
|
|
||
|
var tjd = (this._GREGORIAN_EPOCH - 1) + (365 * (year - 1)) + Math.floor((year - 1) / 4)
|
||
|
-( Math.floor((year - 1) / 100)) + Math.floor((year - 1) / 400) + Math.floor( (739 / 12)
|
||
|
+ ( (dojo.date.isLeapYear(new Date(year,3,1)) ? -1 : -2)) + 1);
|
||
|
|
||
|
var leapadj = ((wjd < tjd ) ? 0 : (dojo.date.isLeapYear(new Date(year,3,1)) ? 1 : 2));
|
||
|
|
||
|
var month = Math.floor((((yearday + leapadj) * 12) + 373) / 367);
|
||
|
var tjd2 = (this._GREGORIAN_EPOCH - 1) + (365 * (year - 1))
|
||
|
+ Math.floor((year - 1) / 4) - (Math.floor((year - 1) / 100))
|
||
|
+ Math.floor((year - 1) / 400) + Math.floor((((367 * month) - 362) / 12)
|
||
|
+ ((month <= 2) ? 0 : (dojo.date.isLeapYear(new Date(year,month,1)) ? -1 : -2)) + 1);
|
||
|
|
||
|
var day = (wjd - tjd2);
|
||
|
|
||
|
var gdate = new Date(year, month-1, day);
|
||
|
|
||
|
gdate.setHours(this._hours);
|
||
|
gdate.setMilliseconds(this._milliseconds);
|
||
|
gdate.setMinutes(this._minutes);
|
||
|
gdate.setSeconds(this._seconds);
|
||
|
|
||
|
return gdate;
|
||
|
},
|
||
|
|
||
|
//TODO: would it make more sense to make this a constructor option? or a static?
|
||
|
// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
|
||
|
fromGregorian:function(/*Date*/gdate){
|
||
|
// summary: This function returns the equivalent Islamic Date value for the Gregorian Date
|
||
|
// example:
|
||
|
// | var dateIslamic = new dojox.date.IslamicDate();
|
||
|
// | var dateGregorian = new Date(2008,10,12);
|
||
|
// | dateIslamic.fromGregorian(dateGregorian);
|
||
|
|
||
|
var date = new Date(gdate);
|
||
|
var gYear = date.getFullYear(),
|
||
|
gMonth = date.getMonth(),
|
||
|
gDay = date.getDate();
|
||
|
|
||
|
var julianDay = (this._GREGORIAN_EPOCH - 1) + (365 * (gYear - 1)) + Math.floor((gYear - 1) / 4)
|
||
|
+ (-Math.floor((gYear - 1) / 100)) + Math.floor((gYear - 1) / 400)
|
||
|
+ Math.floor((((367 * (gMonth+1)) - 362) / 12)
|
||
|
+ (((gMonth+1) <= 2) ? 0 : (dojo.date.isLeapYear(date) ? -1 : -2)) + gDay)
|
||
|
+(Math.floor(date.getSeconds() + 60 * (date.getMinutes() + 60 * date.getHours()) + 0.5) / 86400.0);
|
||
|
julianDay = Math.floor(julianDay) + 0.5;
|
||
|
|
||
|
var days = julianDay - 1948440;
|
||
|
var hYear = Math.floor( (30 * days + 10646) / 10631.0 );
|
||
|
var hMonth = Math.ceil((days - 29 - this._yearStart(hYear)) / 29.5 );
|
||
|
hMonth = Math.min(hMonth, 11);
|
||
|
var hDay = Math.ceil(days - this._monthStart(hYear, hMonth)) + 1;
|
||
|
|
||
|
this._date = hDay;
|
||
|
this._month = hMonth;
|
||
|
this._year = hYear;
|
||
|
this._hours = date.getHours();
|
||
|
this._minutes = date.getMinutes();
|
||
|
this._seconds = date.getSeconds();
|
||
|
this._milliseconds = date.getMilliseconds();
|
||
|
this._day = date.getDay();
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
//TODO i18n: factor out and use CLDR patterns?
|
||
|
parse:function(/*String*/dateObject){
|
||
|
// summary: This function parse the date string
|
||
|
//
|
||
|
// example:
|
||
|
// | var dateIslamic = new dojox.date.IslamicDate();
|
||
|
// | dateIslamic.parse("Safar 2 1429");
|
||
|
|
||
|
var sDate = dateObject.toString();
|
||
|
var template = /\d{1,2}\D\d{1,2}\D\d{4}/;
|
||
|
var sD, jd, mD = sDate.match(template);
|
||
|
if(mD){
|
||
|
mD = mD.toString();
|
||
|
sD = mD.split(/\D/);
|
||
|
this._month = sD[0]-1;
|
||
|
this._date = sD[1];
|
||
|
this._year = sD[2];
|
||
|
}else{
|
||
|
mD = sDate.match(/\D{4,}\s\d{1,2}\s\d{4}/);
|
||
|
if(mD){
|
||
|
mD = mD.toString();
|
||
|
|
||
|
var dayYear = mD.match(/\d{1,2}\s\d{4}/);
|
||
|
dayYear = dayYear.toString();
|
||
|
|
||
|
var mName = mD.replace(/\s\d{1,2}\s\d{4}/,'');
|
||
|
|
||
|
mName = mName.toString();
|
||
|
this._month = dojo.indexOf(this._months, mName); //FIXME: check for -1?
|
||
|
sD = dayYear.split(/\s/);
|
||
|
|
||
|
this._date = sD[0];
|
||
|
this._year = sD[1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var sTime = sDate.match(/\d{2}:/);
|
||
|
if(sTime != null){
|
||
|
sTime = sTime.toString();
|
||
|
var tArr = sTime.split(':');
|
||
|
this._hours = tArr[0];
|
||
|
sTime = sDate.match(/\d{2}:\d{2}/);
|
||
|
if(sTime){
|
||
|
sTime = sTime.toString();
|
||
|
tArr = sTime.split(':');
|
||
|
}
|
||
|
this._minutes = tArr[1] != null ? tArr[1] : 0;
|
||
|
|
||
|
sTime = sDate.match(/\d{2}:\d{2}:\d{2}/);
|
||
|
if(sTime){
|
||
|
sTime = sTime.toString();
|
||
|
tArr = sTime.split(':');
|
||
|
}
|
||
|
this._seconds = tArr[2] != null ? tArr[2]:0;
|
||
|
}else{
|
||
|
this._hours = 0;
|
||
|
this._minutes = 0;
|
||
|
this._seconds = 0;
|
||
|
}
|
||
|
this._milliseconds = 0;
|
||
|
},
|
||
|
|
||
|
|
||
|
valueOf:function(){
|
||
|
// summary: This function returns The stored time value in milliseconds
|
||
|
// since midnight, January 1, 1970 UTC
|
||
|
//
|
||
|
var gdate = this.toGregorian();
|
||
|
return gdate.valueOf();
|
||
|
},
|
||
|
|
||
|
// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
|
||
|
_yearStart:function(/*Number*/year){
|
||
|
//summary: return start of Islamic year
|
||
|
return (year-1)*354 + Math.floor((3+11*year)/30.0);
|
||
|
},
|
||
|
|
||
|
// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
|
||
|
_monthStart:function(/*Number*/year, /*Number*/month){
|
||
|
//summary: return the start of Islamic Month
|
||
|
return Math.ceil(29.5*month) +
|
||
|
(year-1)*354 + Math.floor((3+11*year)/30.0);
|
||
|
},
|
||
|
|
||
|
// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
|
||
|
_civilLeapYear:function(/*Number*/year){
|
||
|
//summary: return Boolean value if Islamic leap year
|
||
|
return (14 + 11 * year) % 30 < 11;
|
||
|
},
|
||
|
|
||
|
// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
|
||
|
getDaysInIslamicMonth:function(/*Number*/month, /*Number*/ year){
|
||
|
//summary: returns the number of days in the given Islamic Month
|
||
|
var length = 0;
|
||
|
length = 29 + ((month+1) % 2);
|
||
|
if(month == 11 && this._civilLeapYear(year)){
|
||
|
length++;
|
||
|
}
|
||
|
return length;
|
||
|
},
|
||
|
|
||
|
_mod:function(a, b){
|
||
|
return a - (b * Math.floor(a / b));
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
//TODOC
|
||
|
dojox.date.IslamicDate.getDaysInIslamicMonth = function(/*dojox.date.IslamicDate*/month){
|
||
|
return new dojox.date.IslamicDate().getDaysInIslamicMonth(month.getMonth(),month.getFullYear()); // dojox.date.IslamicDate
|
||
|
};
|
||
|
|
||
|
dojox.date.IslamicDate._getNames = function(/*String*/item, /*String*/type, /*String?*/use, /*String?*/locale){
|
||
|
// summary:
|
||
|
// Used to get localized strings from dojo.cldr for day or month names.
|
||
|
//
|
||
|
// item:
|
||
|
// 'months' || 'days'
|
||
|
// type:
|
||
|
// 'wide' || 'narrow' || 'abbr' (e.g. "Monday", "Mon", or "M" respectively, in English)
|
||
|
// use:
|
||
|
// 'standAlone' || 'format' (default)
|
||
|
// locale:
|
||
|
// override locale used to find the names
|
||
|
|
||
|
var label;
|
||
|
var lookup = dojo.i18n.getLocalization("dojo.cldr", "islamic", locale);
|
||
|
var props = [item, use, type];
|
||
|
if(use == 'standAlone'){
|
||
|
label = lookup[props.join('-')];
|
||
|
}
|
||
|
props[1] = 'format';
|
||
|
|
||
|
// return by copy so changes won't be made accidentally to the in-memory model
|
||
|
return (label || lookup[props.join('-')]).concat(); /*Array*/
|
||
|
};
|
||
|
|
||
|
dojox.date.IslamicDate.weekDays = dojox.date.IslamicDate._getNames('days', 'wide', 'format');
|
||
|
|
||
|
dojox.date.IslamicDate.months = dojox.date.IslamicDate._getNames('months', 'wide', 'format');
|
||
|
|