Last active
August 29, 2015 14:21
-
-
Save Fardinak/449b4842751579eb1510 to your computer and use it in GitHub Desktop.
A Multi-Calendar-System DateTime Service based on Moment.js (and moment-jalaali)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define(['ng', 'moment-jalaali'], | |
function(ng, moment) { | |
var mod = ng.module('app.service.datetime', []); | |
mod.run(['$rootScope', function($rootScope) { | |
$rootScope.$on('$languageChangeSuccess', function(evt, newLang) { | |
if(newLang === 'fa') moment.loadPersian(); | |
else moment.locale('en'); | |
}); | |
}]); | |
mod.service('calendarSystem', function() { | |
var availableSystems = { | |
GREGORIAN: 0, | |
JALALI: 1 | |
}; | |
var currentSystem = 0; | |
var findByValue = function(value) { | |
for(key in availableSystems) | |
if(value === availableSystems[key]) | |
return key; | |
return null; | |
}; | |
return { | |
SYSTEM: availableSystems, | |
set: function(value) { | |
if(!ng.isNumber(value)) | |
throw new TypeError('A system must be represented with it\'s corresponding integer value.'); | |
if(!findByValue(value)) | |
throw new Error('The provided system is not defined!'); | |
currentSystem = value; | |
}, | |
get: function() { | |
return currentSystem; | |
}, | |
toString: function() { | |
var key = findByValue(currentSystem); | |
if(key) | |
return key.substr(0, 1) + key.substr(1).toLowerCase(); | |
else | |
return "Unknown"; | |
} | |
}; | |
}); | |
// TODO: Switch to mod.provider and join-in the calendarSystem service | |
mod.factory('datetimeService', ['calendarSystem', function(calendarSystem) { | |
// TODO: Add support for forced Gregorian formatting like Jalali (jM -> gM OR use parameters) | |
// var formattingTokens = /(\\)?(j|g)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|w[o|w]?|YYYYY|YYYY|YY|gg(ggg?)?|)/g, | |
var formattingTokens = /(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|w[o|w]?|YYYYY|YYYY|YY|gg(ggg?)?|)/g, | |
sharedTokens = ['M', 'MM', 'MMM', 'MMMM', 'D', 'DD', 'DDD', 'w', 'YY', 'YYYY', 'YYYYY', 'gg', 'gggg', 'ggggg']; | |
// Bind directly | |
var _simpleBind = function(fn) { | |
return function() { | |
var result = this.$moment[fn].apply(this.$moment, arguments); | |
return moment.isMoment(result) ? this : result; | |
}; | |
}; | |
// Bind to jFn or fn based on calendar system flag | |
var _gjBind = function(fn) { | |
var jFn = 'j' + fn.substr(0, 1).toUpperCase() + fn.substr(1); | |
return function() { | |
var result = this.$moment[this.isJalali ? jFn : fn].apply(this.$moment, arguments); | |
return moment.isMoment(result) ? this : result; | |
} | |
}; | |
// Bind directly but reformat specified parameter | |
var _gjParamBind = function(fn, paramIndex) { | |
return function() { | |
if(this.isJalali) { | |
var value = arguments[paramIndex]; | |
arguments[paramIndex] = 'j' + value; | |
} | |
var result = this.$moment[fn].apply(this.$moment, arguments); | |
return moment.isMoment(result) ? this : result; | |
} | |
}; | |
function DTS() { | |
// General functions | |
this.isDSTShifted = _simpleBind('isDSTShifted'); | |
this.invalidAt = _simpleBind('invalidAt'); | |
this.isValid = _simpleBind('isValid'); | |
this.local = _simpleBind('local'); | |
this.parsingFlags = _simpleBind('parsingFlags'); | |
this.unix = _simpleBind('unix'); | |
this.utc = _simpleBind('utc'); | |
this.weekday = _simpleBind('weekday'); | |
this.toString = _simpleBind('toString'); | |
this.toDate = _simpleBind('toDate'); | |
this.toISOString = _simpleBind('toISOString'); | |
this.toArray = _simpleBind('toArray'); | |
this.valueOf = _simpleBind('valueOf'); | |
// Calculating functions | |
this.add = _gjParamBind('add', 1); // reformats add(1, 'month') to add(1, 'jMonth') if the jalali flag is set | |
this.endOf = _gjParamBind('endOf', 0); | |
this.startOf = _gjParamBind('startOf', 0); | |
this.subtract = _gjParamBind('subtract', 1); | |
// Shared date functions | |
this.date = _gjBind('date'); // reformats date(...) to jDate(...) if the jalali flag is set | |
this.dates = _gjBind('dates'); | |
this.dayOfYear = _gjBind('dayOfYear'); | |
this.month = _gjBind('month'); | |
this.months = _gjBind('months'); | |
this.week = _gjBind('week'); | |
this.weekYear = _gjBind('weekYear'); | |
this.weeks = _gjBind('weeks'); | |
this.year = _gjBind('year'); | |
this.years = _gjBind('years'); | |
// Gregorian-specific functions | |
this.gDate = _simpleBind('date'); | |
this.gDates = _simpleBind('dates'); | |
this.gDayOfYear = _simpleBind('dayOfYear'); | |
this.gMonth = _simpleBind('month'); | |
this.gMonths = _simpleBind('months'); | |
this.gWeek = _simpleBind('week'); | |
this.gWeekYear = _simpleBind('weekYear'); | |
this.gWeeks = _simpleBind('weeks'); | |
this.gYear = _simpleBind('year'); | |
this.gYears = _simpleBind('years'); | |
// Jalali-specific functions | |
this.jDate = _simpleBind('jDate'); | |
this.jDates = _simpleBind('jDates'); | |
this.jDayOfYear = _simpleBind('jDayOfYear'); | |
this.jMonth = _simpleBind('jMonth'); | |
this.jMonths = _simpleBind('jMonths'); | |
this.jWeek = _simpleBind('jWeek'); | |
this.jWeekYear = _simpleBind('jWeekYear'); | |
this.jWeeks = _simpleBind('jWeeks'); | |
this.jYear = _simpleBind('jYear'); | |
this.jYears = _simpleBind('jYears'); | |
// Special bindings | |
this.clone = function() { | |
var dts = new DateTimeService(); | |
dts.$moment = this.$moment.clone.call(this.$moment); | |
dts.isJalali = this.isJalali; | |
return dts; | |
}; | |
this.format = function(format) { | |
if (this.isJalali) { | |
format = format.replace(formattingTokens, function(m) { | |
return (sharedTokens.indexOf(m) > -1 ? 'j' : '') + m; | |
}); | |
} | |
return this.$moment.format.apply(this.$moment, arguments); | |
}; | |
// TODO: Replace with the following line when jMoment.isSame is available in jMoment | |
// this.isSame = _gjParamBind('isSame', 1); | |
this.isSame = function(input, units) { | |
var inputMs; | |
units = (units || 'millisecond').toLowerCase(); | |
if (units === 'millisecond') { | |
input = DateTimeService(input); | |
return +this === +input; | |
} else { | |
inputMs = +DateTimeService(input); | |
return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); | |
} | |
}; | |
}; | |
function DateTimeService(input, format, lang, utc) { | |
if(input instanceof DTS) return input; | |
var dts = new DTS; | |
if(utc) | |
dts.$moment = moment.utc(input, format, lang); | |
else | |
dts.$moment = moment(input, format, lang); | |
dts.isJalali = calendarSystem.get() === calendarSystem.SYSTEM.JALALI; | |
return dts; | |
}; | |
return DateTimeService; | |
}]); | |
return mod; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment