/** * Instruments Ext.Date object and adds support for Jalali calendar to it. * *

Usage is very simple. Examples: *


 var date;
 date = new Date();
 console.log(Ext.Date.getJalaliFullYear(date)); // current year in Jalali calendar
 console.log(Ext.Date.getJalaliMonth(date)); // current month in Jalali calendar (0-based)
 console.log(Ext.Date.getJalaliDate(date)); // current date in Jalali calendar
 console.log(Ext.Date.isJalaliLeapYear(date)); // true if this is a leap year in Jalali calendar
 console.log(Ext.Date.format(Ext.Date.addJalali(date, Ext.Date.MONTH, -3), 'Jalali')); // subtracts a month in Jalali calendar
 console.log(Ext.Date.getJalaliDaysInMonth(date)); // count of days in current Jalali month
 console.log(Ext.Date.getJalaliFirstDateOfMonth(date)); // date of the first day of current month in Jalali calendar
 * 
* There are some useful methods. Be sure to read the documentation. * *

Gregorian to Jalali conversion is based on algorithm provided by farsiweb.info * (see http://www.farsiweb.info/jalali/jalali.js). */ (function () { 'use strict'; Ext.define('Ext.ux.JalaliDate', { override: 'Ext.Date', /** * Validates a Jalali date. * @param y Year value. * @param m Month value, 1-based. * @param d Date value. * @return {Boolean} True if valid, false otherwise. */ isJalaliValid: function (y, m, d) { var g, j; if (y > 1500 || y < 1 || m > 12 || m < 1 || d > 31 || d < 1) { return false; } g = Ext.Date.JalaliConverter.jalaliToGregorian([y, m, d]); j = Ext.Date.JalaliConverter.gregorianToJalali(g); return j[0] === y && j[1] === m && j[2] === d; }, /** * Corrects Jalali date of month if the date is invalid for the specified month of year. * @param {Number} year Jalali full year. * @param {Number} month Jalali month (0-based). * @param {Number} date Jalali date. * @return {Number} Corrected Jalali date. */ correctJalaliDateOfMonth: function (year, month, date) { var d = Math.max(1, Math.min(31, date)); if (month === 11 && d > 29) { if (Ext.Date.isJalaliLeapYear(year)) { d = 30; } else { d = 29; } } else if (month > 5 && d > 30) { d = 30; } return d; }, /** * Creates a new date instance based on the provided Jalali year, month (0-based) and date. * @param {Number} year Jalali full year. * @param {Number} month Jalali month (0-based). * @param {Number} date Jalali date. */ createJalali: function (year, month, date) { var g = Ext.Date.JalaliConverter.jalaliToGregorian([year, month + 1, date]); return new Date(g[0], g[1] - 1, g[2], 12); }, /** * Parses a Jalali formatted date string (like "1389/06/09") and returns a Date object. * @param {String} jalaliString Formatted string to parse. * @param {Boolean} strict True to validate date strings after parsing which will return null when invalid * (default is false). * @return {Date} A Date object which is set to the Gregorian conversion of input. */ parseJalali: function (jalaliString, strict) { var g, d, split = jalaliString.split('/'), jy = parseInt(split[0], 10), jm = parseInt(split[1], 10), jd = parseInt(split[2], 10); if (isNaN(jy) || isNaN(jm) || isNaN(jd) || jy > 1500 || jy < 1 || jm > 12 || jm < 1 || jd > 31 || jd < 1) { return null; } g = Ext.Date.JalaliConverter.jalaliToGregorian([jy, jm, jd]); d = new Date(g[0], g[1] - 1, g[2], 12); if (strict && (!d || Ext.Date.getJalaliFullYear(d) !== jy || Ext.Date.getJalaliMonth(d) + 1 !== jm || Ext.Date.getJalaliDate(d) !== jd)) { return null; } return d; }, /** * Converts date to Jalali date. * @param {Date} gregorian date * @return {Object} with jalaliYear, jalaliMonth (0-based) and jalaliDate properties. */ convertToJalali: function (date) { var j = Ext.Date.JalaliConverter.gregorianToJalali([date.getFullYear(), date.getMonth() + 1, date.getDate()]); return { jalaliYear: j[0], jalaliMonth: j[1] - 1, jalaliDate: j[2] }; }, /** * Returns Jalali full year. * @param {Date} gregorian date * @return {Number} Jalali year. */ getJalaliFullYear: function (date) { return Ext.Date.convertToJalali(date).jalaliYear; }, /** * Returns Jalali month. Month is 0-based. * @param {Date} gregorian date * @return {Number} Jalali month of year (0-based). */ getJalaliMonth: function (date) { return Ext.Date.convertToJalali(date).jalaliMonth; }, /** * Returns Jalali date of month. * @param {Date} gregorian date * @return {Number} Jalali date of month. */ getJalaliDate: function (date) { return Ext.Date.convertToJalali(date).jalaliDate; }, /** * Checks if the date or year is a Jalali leap year. * @param {Date/Number} date Gregorian date or Jalali year * @return {Boolean} True if the current date or year is a Jalali leap year, false otherwise. */ isJalaliLeapYear: function (date) { var year = date; if (Object.prototype.toString.call(date) === '[object Date]') { year = Ext.Date.convertToJalali(date).jalaliYear; } return Ext.Date.isJalaliValid(year, 12, 30); }, /** * Provides a convenient method for performing basic Jalali date arithmetic. It creates and returns * a new Date instance containing the resulting date value. * @param {Date} date Starting date * @param {String} interval A valid date interval enum value. * @param {Number} value The amount to add to the current date. * @return {Date} The new Date instance. */ addJalali: function (date, interval, value) { var jd, gd, d = new Date(date.getTime()); if (!interval || value === 0) { return d; } jd = Ext.Date.convertToJalali(d); switch (interval.toLowerCase()) { case Ext.Date.DAY: jd.jalaliDate += value; break; case Ext.Date.MONTH: jd.jalaliMonth += value; jd.jalaliYear += Math.floor(jd.jalaliMonth / 12); jd.jalaliMonth %= 12; if (jd.jalaliMonth < 0) { jd.jalaliMonth += 12; } jd.jalaliDate = Ext.Date.correctJalaliDateOfMonth(jd.jalaliYear, jd.jalaliMonth, jd.jalaliDate); break; case Ext.Date.YEAR: jd.jalaliYear += value; jd.jalaliDate = Ext.Date.correctJalaliDateOfMonth(jd.jalaliYear, jd.jalaliMonth, jd.jalaliDate); break; } gd = Ext.Date.JalaliConverter.jalaliToGregorian([jd.jalaliYear, jd.jalaliMonth + 1, jd.jalaliDate]); d.setFullYear(gd[0]); d.setMonth(gd[1] - 1); d.setDate(gd[2]); return d; }, /** * Returns the number of days in the current Jalali month, adjusted for leap year. * @param {Date} date Starting date * @return {Number} The number of days in the current Jalali month. */ getJalaliDaysInMonth: function (date) { var days, jd = Ext.Date.convertToJalali(date); if (jd.jalaliMonth < 6) { days = 31; } else if (jd.jalaliMonth < 11) { days = 30; } else if (Ext.Date.isJalaliLeapYear(jd.jalaliYear)) { days = 30; } else { days = 29; } return days; }, /** * Returns the date of the first day of the Jalali month. * @param {Date} date Starting date * @return {Date} The date of the first day of the Jalali month. */ getJalaliFirstDateOfMonth: function (date) { var jd = Ext.Date.convertToJalali(date); return Ext.Date.createJalali(jd.jalaliYear, jd.jalaliMonth, 1); }, /** * Month names of Jalali calendar. Override this for localization. */ jalaliMonthNames: [ 'Farvardin', 'Ordibehesht', 'Khordad', 'Tir', 'Amordad', 'Shahrivar', 'Mehr', 'Aban', 'Azar', 'Dey', 'Bahman', 'Esfand' ] }, function () { /** * Jalali format codes. List of Jalali format codes: *


         Format  Description                                                          Example returned values
         ------  -------------------------------------------------------------------  -----------------------
           r     Jalali day of the month without leading zeros                        1 to 31
           R     Jalali day of the month, 2 digits with leading zeros                 01 to 31
           q     Numeric representation of Jalali month without leading zeros         1 to 12
           Q     Numeric representation of Jalali month, 2 digits with leading zeros  01 to 12
           e     Full textual representation of Jalali month                          Farvardin to Esfand
           b     Short representation of Jalali year, 2 digits                        89 or 60
           B     Full numeric representation of Jalali year, 4 digits                 1389 or 1360
         * 
* Example usage: *

         var d = new Date();
         console.log(Ext.Date.format(d, 'B/Q/R'));     // 1389/06/14
         console.log(Ext.Date.format(d, 'b/q/r'));     // 89/6/14
         console.log(Ext.Date.format(d, 'l, r e B'));  // Sunday, 14 Shahrivar 1389
         * 
*/ Ext.apply(Ext.Date.formatCodes, { r: "Ext.Date.getJalaliDate(this)", R: "Ext.String.leftPad(Ext.Date.getJalaliDate(this), 2, '0')", q: "(Ext.Date.getJalaliMonth(this) + 1)", Q: "Ext.String.leftPad(Ext.Date.getJalaliMonth(this) + 1, 2, '0')", e: "Ext.Date.jalaliMonthNames[Ext.Date.getJalaliMonth(this)]", b: "('' + Ext.Date.getJalaliFullYear(this)).substring(2, 4)", B: "Ext.Date.getJalaliFullYear(this)" }); Ext.apply(Ext.Date.formatFunctions, { /** * Formats date instances using Jalali format (like: "1389/06/14"). * @return {String} Textual representation of Jalali date. */ 'Jalali': function () { var jd = Ext.Date.convertToJalali(this); return jd.jalaliYear + '/' + Ext.String.leftPad(jd.jalaliMonth + 1, 2, '0') + '/' + Ext.String.leftPad(jd.jalaliDate, 2, '0'); } }); Ext.apply(Ext.Date.parseFunctions, { /** * Parses a Jalali formatted date string (like "1389/06/09") and returns a Date object. * @param {String} jalaliString Formatted string to parse. * @param {Boolean} strict True to validate date strings after parsing which will return null when invalid * (default is false). * @return {Date} A Date object which is set to the Gregorian conversion of input. */ 'Jalali': Ext.Date.parseJalali, 'B/Q/R': Ext.Date.parseJalali, 'B/q/r': Ext.Date.parseJalali, 'b/q/r': function (value, strict) { return Ext.Date.parseJalali('13' + value, strict); }, 'b/Q/R': function (value, strict) { return Ext.Date.parseJalali('13' + value, strict); }, 'B': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(value + '/' + (Ext.Date.getJalaliMonth(now) + 1) + '/' + Ext.Date.getJalaliDate(now), strict); }, 'b': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali('13' + value + '/' + (Ext.Date.getJalaliMonth(now) + 1) + '/' + Ext.Date.getJalaliDate(now), strict); }, 'q': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + value + '/' + Ext.Date.getJalaliDate(now), strict); }, 'Q': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + value + '/' + Ext.Date.getJalaliDate(now), strict); }, 'r': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + (Ext.Date.getJalaliMonth(now) + 1) + '/' + value, strict); }, 'R': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + (Ext.Date.getJalaliMonth(now) + 1) + '/' + value, strict); }, 'b/q': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali('13' + value + '/' + Ext.Date.getJalaliDate(now), strict); }, 'B/q': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(value + '/' + Ext.Date.getJalaliDate(now), strict); }, 'B/Q': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(value + '/' + Ext.Date.getJalaliDate(now), strict); }, 'b/Q': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali('13' + value + '/' + Ext.Date.getJalaliDate(now), strict); }, 'q/r': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + value, strict); }, 'Q/r': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + value, strict); }, 'Q/R': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + value, strict); }, 'q/R': function (value, strict) { var now = new Date(); return Ext.Date.parseJalali(Ext.Date.getJalaliFullYear(now) + '/' + value, strict); } }); }); }());