basic-shamsi
Version:
Converts, validate, manipulate, and display Shamsi (Jalaali) and Miladi (Gregorian) dates
407 lines (361 loc) • 17.7 kB
JavaScript
var is_positive = n => !isNaN(n) && n > 0;
const DateHelper = {
IsDate: function (input) { return Object.prototype.toString.call(input) === "[object Date]"; },
IsValid: function (value, cal) {
var ymd = this.YMD(value);
return ymd.length === 3 && is_positive(ymd[0]) && is_positive(ymd[1]) && is_positive(ymd[2]) && ymd[1] <= 12 && ymd[2] <= cal.daysInMonth(ymd[0], ymd[1]);
},
ValidateShamsi: function (ymd) {
ymd = this.YMD(ymd);
if (!ymd) return null;
var y = ymd[0];
var m = ymd[1];
var d = ymd[2];
if (!y) y = 1;
if (!m) m = 1;
if (!d) d = 1;
//--------
while (m < 1) { m += 12; y -= 1; };
while (m > 12) { m -= 12; y += 1; };
//--------
while (d < 1) {
m -= 1;
if (m < 1) { m += 12; y -= 1; }
d += Shamsi.daysInMonth(y, m);
};
while (d > Shamsi.daysInMonth(y, m)) {
d -= Shamsi.daysInMonth(y, m);
m += 1;
if (m > 12) { m -= 12; y += 1; }
};
return [y, m, d];
},
ValidateMiladi: function (ymd) {
ymd = this.YMD(ymd);
if (!ymd) return null;
var y = ymd[0];
var m = ymd[1];
var d = ymd[2];
if (!y) y = 1;
if (!m) m = 1;
if (!d) d = 1;
//--------
while (m < 1) { m += 12; y -= 1; };
while (m > 12) { m -= 12; y += 1; };
//--------
while (d < 1) {
m -= 1;
if (m < 1) { m += 12; y -= 1; }
d += Miladi.daysInMonth(y, m);
};
while (d > Miladi.daysInMonth(y, m)) {
d -= Miladi.daysInMonth(y, m);
m += 1;
if (m > 12) { m -= 12; y += 1; }
};
return [y, m, d];
},
YMD: function (ymd) {
if (DateHelper.IsDate(ymd)) return [ymd.getFullYear(), ymd.getMonth() + 1, ymd.getDate(), ymd.getHours(), ymd.getMinutes(), ymd.getSeconds(), ymd.getMilliseconds()]
else if (typeof (ymd) === 'string') {
if (ymd.indexOf('-') > 0 && ymd.indexOf('T') > 0) {
var s = ymd.trim().split('T')[0]
ymd = s.split('-')
}
else {
var s = ymd.trim().split(' ')[0]
ymd = s.split('/')
}
}
else if (Array.isArray(ymd) && ymd.length < 3) {
var a = [];
for (var i = 0; i < ymd.length; i++) a.push(ymd[i]);
ymd = a;
while (ymd.length < 3) ymd.push(1);
}
else if (!Array.isArray(ymd)) return null;
for (var k = 0; k < ymd.length; k++)
ymd[k] = ymd[k] * 1;
return ymd;
},
YMD2Date: function (ymd) { return new Date(ymd[0], ymd[1] - 1, ymd[2]); },
format: function (fmt, ymd, calendar) {
ymd = DateHelper.YMD(ymd);
if (!ymd) return null;
if (!fmt) fmt = 'yyyy/MM/dd';
var y = ymd[0] * 1;
var m = ymd[1] * 1;
var d = ymd[2] * 1;
var hh = ymd.length > 3 ? ymd[3] : 0;
var mm = ymd.length > 4 ? ymd[4] : 0;
var ss = ymd.length > 5 ? ymd[5] : 0;
var zz = ymd.length > 6 ? ymd[6] : 0;
zz = zz < 10 ? '00' + zz : (zz < 100 ? '0' + zz : zz + '');
var res = '';
for (var i = 0; i < fmt.length; i++) {
var c = fmt[i];
var n = 1;
while (i + 1 < fmt.length && fmt[i + 1] === c) {
i += 1;
n += 1;
}
switch (c) {
case 'y':
case 'Y':
if (n === 2 && ((y >= 1300 && y < 1400) || (y >= 1900 && y < 2000))) res += (y % 100) + '';
else res += y + '';
break;
case 'M':
if (n === 1) res += m + '';
else if (n === 2) res += (m < 10 ? '0' : '') + m;
else res += calendar.getMonthName(m);
break;
case 'd':
case 'D':
if (n === 1) res += d + '';
else if (n === 2) res += (d < 10 ? '0' : '') + d;
else res += calendar.getDOWName(y, m, d);
break;
case 'h':
var _hh = hh > 12 ? hh - 12 : hh;
if (n === 1) res += _hh + '';
else res += (_hh < 10 ? '0' : '') + _hh;
break;
case 'H':
if (n === 1) res += hh + '';
else res += (hh < 10 ? '0' : '') + hh;
break;
case 'm':
if (n === 1) res += mm + '';
else res += (mm < 10 ? '0' : '') + mm;
break;
case 's':
if (n === 1) res += ss + '';
else res += (ss < 10 ? '0' : '') + ss;
break;
case 'z':
if (n === 1) res += zz.substr(0, 1);
else if (n === 2) res += zz.substr(0, 2);
else res += zz;
break;
default:
while (n-- > 0) res += c;
break;
}
}
return res;
}
}
export const Miladi = new function () {
var self = this;
var leaps = [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 292, 296, 304, 308, 312, 316, 320, 324, 328, 332, 336, 340, 344, 348, 352, 356, 360, 364, 368, 372, 376, 380, 384, 388, 392, 396]
var dow = [4, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3,];
var dow_names = ['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
var month_len = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var m_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
self.Id = "miladi";
self.year_start = 1800;
self.year_end = self.year_start + 400;
self.GoToTodayText = 'Today';
self.short_dow_names = ['Sa', 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr'];
self.NextMonthText = 'Next Month';
self.PrevMonthText = 'Previous Month';
function ymd_to_days(ymd) {
ymd = DateHelper.YMD(ymd);
if (!ymd) return 0;
//------------------
var y = ymd[0];
var days = ymd[2] - 1;
for (var i = self.year_start; i < y; i++) days += self.isleap(i) ? 366 : 365;
for (i = 1; i < ymd[1]; i++) days += self.daysInMonth(y, i);
return days;
}
function days_to_ymd(days) {
var y = self.year_start;
var m = 1;
var d = 1;
//------------------
while (days > 0) {
var days_in_year = self.isleap(y) ? 366 : 365;
if (days < days_in_year) break;
y += 1;
days -= days_in_year;
}
//------------------
while (days > 0) {
var days_in_month = self.daysInMonth(y, m);
if (days < days_in_month) break;
m += 1;
days -= days_in_month;
}
if (days > 0) d += days;
return [y, m, d];
}
self.isleap = function (y) {
y -= self.year_start;
for (var i = 0; i < leaps.length && leaps[i] <= y; i++)
if (leaps[i] === y) return true;
return false;
}
self.daysInMonth = function (y, m) {
while (m < 1) m += 12;
while (m > 12) m -= 12;
return m === 2 && self.isleap(y) ? 29 : month_len[m - 1];
}
self.getMonthName = function (m) { return m < 1 || m > 12 ? null : m_names[m - 1]; }
self.getDOWName = function (y, m, d) { return dow_names[self.DOW(y, m, d)]; }
self.DOW = function (y, m, d) {
var d1_1 = dow[y - self.year_start];
var m_dow = [0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5];
var res = (d1_1 + m_dow[m - 1]) % 7;
if (d > 0) res = (res + (d - 1)) % 7;
return res;
}
self.addDaysYMD = function (ymd, amount) {
if (ymd == null) ymd = [self.year_start, 1, 1];
var days = ymd_to_days(ymd);
return days_to_ymd(days + amount);
}
self.addDays = function (ymd, amount) { return DateHelper.format("yyyy/MM/dd", self.addDaysYMD(ymd, amount), self) }
self.addMonths = function (ymd, amount) {
ymd = DateHelper.YMD(ymd);
if (!ymd) return null;
var y = ymd[0];
var m = ymd[1] + amount;
var d = ymd[2];
//-------------
while (m < 1) { m += 12; y -= 1; };
while (m > 12) { m -= 12; y += 1; };
return DateHelper.format("yyyy/MM/dd", [y, m, d], self);
}
self.subtract = function (ymd1, ymd2) { return ymd_to_days(ymd1) - ymd_to_days(ymd2); }
self.baseOffset = function (ymd) { return ymd_to_days([1821, 3, 21]) }
self.toShamsiYMD = function (ymd) {
var x = ymd_to_days(ymd) - self.baseOffset() + Shamsi.baseOffset();
return Shamsi.addDaysYMD(null, x);
}
self.toShamsi = function (ymd) { return DateHelper.format('yyyy/MM/dd', self.toShamsiYMD(ymd), self); }
self.parse = function (ymd) { return DateHelper.YMD2Date(DateHelper.YMD(ymd)); }
self.now = function () {
var dt = new Date();
var m = dt.getMonth() + 1; //months from 1-12
var d = dt.getDate();
var y = dt.getFullYear();
var res = y + "/" + (m < 10 ? "0" : "") + m + "/" + (d < 10 ? "0" : "") + d;
return res;
}
self.validate = function (value) { return DateHelper.ValidateMiladi(value); }
self.isValid = function (value) { return DateHelper.IsValid(value, self) }
self.format = function (dateFormat, value) { return DateHelper.format(dateFormat, DateHelper.YMD(value), self) }
}();
export const Shamsi = new function () {
var self = this;
var leaps = [1, 5, 10, 14, 18, 22, 26, 30, 34, 38, 43, 47, 51, 55, 59, 63, 67, 71, 76, 80, 84, 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 129, 133, 137, 142, 146, 150, 154, 158, 162, 166, 170, 175, 179, 183, 187, 191, 195, 199, 203, 208, 212, 216, 220, 224, 228, 232, 236, 241, 245, 249, 253, 257, 261, 265, 269, 274, 278, 282, 286, 290, 294, 298]
var dow = [4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 1, 3, 4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 5, 0, 1, 2, 3, 5]
var dow_names = ['شنبه', 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه'];
var m_names = ['فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'];
self.Id = "shamsi";
self.year_start = 1200;
self.year_end = self.year_start + 400;
self.GoToTodayText = 'برو به امروز';
self.short_dow_names = ['ش', 'ی', 'د', 'س', 'چ', 'پ', 'ج'];
self.NextMonthText = 'ماه بعد';
self.PrevMonthText = 'ماه قبل';
function ymd_to_days(ymd) {
ymd = DateHelper.YMD(ymd);
if (!ymd) return 0;
//------------------
var y = ymd[0];
var days = ymd[2] - 1;
for (var i = self.year_start; i < y; i++) days += self.isleap(i) ? 366 : 365;
for (i = 1; i < ymd[1]; i++) days += self.daysInMonth(y, i);
return days;
}
function days_to_ymd(days) {
var y = self.year_start;
var m = 1;
var d = 1;
//------------------
while (days > 0) {
var days_in_year = self.isleap(y) ? 366 : 365;
if (days < days_in_year) break;
y += 1;
days -= days_in_year;
}
//------------------
while (days > 0) {
var days_in_month = self.daysInMonth(y, m);
if (days < days_in_month) break;
m += 1;
days -= days_in_month;
}
if (days > 0) d += days;
return [y, m, d];
}
self.isleap = function (y) {
y -= self.year_start;
for (var i = 0; i < leaps.length && leaps[i] <= y; i++)
if (leaps[i] === y) return true;
return false;
}
self.daysInMonth = function (y, m) {
while (m < 1) m += 12;
while (m > 12) m -= 12;
return m < 7 ? 31 : (m < 12 || self.isleap(y) ? 30 : 29);
}
self.getMonthName = function (m) { return m < 1 || m > 12 ? null : m_names[m - 1]; }
self.getDOWName = function (y, m, d) { return dow_names[self.DOW(y, m, d)]; }
self.DOW = function (y, m, d) {
var d1_1 = dow[y - self.year_start];
var m_dow = [0, 3, 6, 2, 5, 1, 4, 6, 1, 3, 5, 0];
var res = (d1_1 + m_dow[m - 1]) % 7;
if (d > 0) res = (res + (d - 1)) % 7;
return res;
}
self.addDaysYMD = function (ymd, amount) {
if (ymd == null) ymd = [self.year_start, 1, 1];
var days = ymd_to_days(ymd);
return days_to_ymd(days + amount);
}
self.addDays = function (ymd, amount) { return DateHelper.format("yyyy/MM/dd", self.addDaysYMD(ymd, amount), self) }
self.addMonths = function (ymd, amount) {
ymd = DateHelper.YMD(ymd);
if (!ymd) return null;
var y = ymd[0];
var m = ymd[1] + amount;
var d = ymd[2];
//-------------
while (m < 1) { m += 12; y -= 1; };
while (m > 12) { m -= 12; y += 1; };
return DateHelper.format("yyyy/MM/dd", [y, m, d], self);
}
self.subtract = function (ymd1, ymd2) {
if (DateHelper.IsDate(ymd1)) ymd1 = Miladi.toShamsiYMD(ymd1)
if (DateHelper.IsDate(ymd2)) ymd2 = Miladi.toShamsiYMD(ymd2)
return ymd_to_days(ymd1) - ymd_to_days(ymd2);
}
self.baseOffset = function () { return ymd_to_days([1200, 1, 1]) }
self.toMiladiYMD = function (ymd) {
if (DateHelper.IsDate(ymd)) return Miladi.format("yyyy/MM/dd", ymd);
var x = ymd_to_days(ymd) - self.baseOffset() + Miladi.baseOffset();
return Miladi.addDaysYMD(null, x);
}
self.toMiladi = function (ymd) { return DateHelper.format('yyyy/MM/dd', self.toMiladiYMD(ymd), self); }
self.parse = function (ymd) { return DateHelper.YMD2Date(self.toMiladiYMD(ymd)); }
self.now = function () { return Miladi.toShamsi(new Date()); }
self.validate = function (value) { return DateHelper.ValidateShamsi(value); }
self.isValid = function (value) { return DateHelper.IsValid(value, self) }
self.format = function (dateFormat, value) {
var is_sys_date = DateHelper.IsDate(value);
var ymd = is_sys_date ? Miladi.toShamsiYMD(value) : DateHelper.YMD(value);
if (is_sys_date) ymd = [ymd[0], ymd[1], ymd[2], value.getHours(), value.getMinutes(), value.getSeconds(), value.getMilliseconds()];
return DateHelper.format(dateFormat, ymd, self)
}
}();
//var NowYMD_HHMM = function () {
// var t = new Date();
// return Calendar.now() + ' ' + t.getHours() + ':' + t.getMinutes();
//}
//alert(Shamsi.toMiladi('1397/07/11'));
//alert(Miladi.toShamsi('2018/10/03'));
//var Calendar = Shamsi;