Skip to content

Instantly share code, notes, and snippets.

@myaumyau
Last active September 28, 2015 21:38
Show Gist options
  • Save myaumyau/1500087 to your computer and use it in GitHub Desktop.
Save myaumyau/1500087 to your computer and use it in GitHub Desktop.
[js]DateTime.js
(function(namespace) {
// local symbol
var _win = window, _ns = _win;
if (namespace) {
var nsArr = namespace.split('.');
for (var i = 0, l = nsArr.length; i < l; i++) {
var ns = nsArr[i];
if (typeof(_ns[ns]) == 'undefined') _ns[ns] = {};
_ns = _ns[ns];
}
}
var _pad = function(value, totalWidth, paddingChar, isLeft) {
var ret = '' + value;
if (!totalWidth) {
totalWidth = ret.length + 1;
}
if (!paddingChar) {
paddingChar = (typeof value === 'number') ? '0' : ' ';
}
while(ret.length < totalWidth) {
ret = !!isLeft ? paddingChar + ret : ret + paddingChar;
}
return ret;
};
var _padLeft = function(value, totalWidth, paddingChar) {
return _pad(value, totalWidth, paddingChar, true);
};
/**
* DateTime
* new DateTime(); //= DateTime.now
* new DateTime(totalMillisec);
* new DateTime(year,month,day);
* new DateTime(year,month,day,hour,minute,second);
*/
DateTime = function() {
this.initialize.apply(this, arguments);
};
DateTime.cultures = {
jajp: {
diffUTC: 9,
apNames :{
full: { AM: '午前', PM: '午後'},
short: { AM: 'AM', PM: 'PM'}
},
dayNames: {
//monday,tuesday,wednesday,thursday,friday,saturday,sunday
full: new Array('日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'),
short:new Array('日' ,'月' ,'火' ,'水' ,'木' ,'金' ,'土')
},
monthNames: {
// januray,february,march,april,may,june,july,august,september,october,november,december
full: new Array('1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'),
short:new Array('1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'10' ,'11' ,'12')
}
}
};
DateTime.cultures = {
def: DateTime.cultures.jajp,
jajp: DateTime.cultures.jajp
};
DateTime.regExpFormat = /dddd|ddd|dd|d|fff|ff|f|hh|h|HH|H|mm|m|MMMM|MMM|MM|M|ss|s|tt|t|yyyy|yyy|yy|y/g;
DateTime.daysMonth = new Array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365);
DateTime.daysMonthLeapYear = new Array(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366);
DateTime.isLeapYear = function(year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
};
DateTime.daysInMonth = function(year, month) {
if (DateTime.isLeapYear(year)) {
return DateTime.daysMonthLeapYear[month] - DateTime.daysMonthLeapYear[month - 1];
} else {
return DateTime.daysMonth[month] - DateTime.daysMonth[month - 1];
}
};
DateTime.now = function() {
var d = new Date();
return new DateTime(d.getFullYear(), d.getMonth() + 1, d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
};
DateTime.today = function() {
var d = new Date();
return new DateTime(d.getFullYear(), d.getMonth() + 1, d.getDate());
};
DateTime.utcNow = function() {
var d = new Date();
return new DateTime(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
};
DateTime.prototype = {
/* Constractor */
initialize: function() {
this.culture = DateTime.cultures.def;
var days = 0, year = 0, month = 0, day = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
var toNum = function(val) {
var type = typeof val;
if (type === 'number') return val;
if (type === 'string' && !!val) return parseInt(val.replace(/^0+/, ''));
throw('invalid argument.');
};
switch (arguments.length) {
case 0:
var d = new Date();
year = d.getFullYear();
month = d.getMonth() + 1;
day = d.getDate();
hours = d.getHours();
minutes = d.getMinutes();
seconds = d.getSeconds();
milliseconds = d.getMilliseconds();
break;
case 1:
milliseconds = toNum(arguments[0]);
break;
case 3:
year = toNum(arguments[0]);
month = toNum(arguments[1]);
day = toNum(arguments[2]);
break;
case 7:
year = toNum(arguments[0]);
month = toNum(arguments[1]);
day = toNum(arguments[2]);
hours = toNum(arguments[3]);
minutes = toNum(arguments[4]);
seconds = toNum(arguments[5]);
milliseconds = toNum(arguments[6]);
break;
default:
throw('invalid arguments.length.');
}
days = (!year && !month && !day) ? 0 : this._ymd2days(year, month, day);
this.timespan = new TimeSpan(days, hours, minutes, seconds, milliseconds);
},
/* Methods */
add: function(timespan) {
return new DateTime(this.totalMilliseconds() + timespan.totalMilliseconds());
},
addDays: function(days) {
return this.add(new TimeSpan(days, 0, 0, 0));
},
addHours: function(hours) {
return this.add(new TimeSpan(hours, 0, 0));
},
addMilliseconds: function(milliseconds) {
return this.add(new TimeSpan(0, 0, 0, 0, milliseconds));
},
addMinutes: function(minutes) {
return this.add(new TimeSpan(0, minutes, 0));
},
addMonths: function(months) {
var day = this.day(), month = this.month() + (months % 12), year = this.year() + Math.round(months / 12);
if (12 < month) {
month -= 12;
year++;
} else if (month < 1) {
month += 12;
}
var days = DateTime.daysInMonth(year, month);
// 2010/3/29 -1month => 2010/02/28
day = (days < day) ? days : day;
return new DateTime(year, month, day).add(this.timeOfDay());
},
addSeconds: function(seconds) {
return this.add(new TimeSpan(0, 0, seconds));
},
addYears: function(years) {
return this.addMonths(years * 12);
},
compareTo : function(datetime){
return this.timespan.compareTo(datetime.timespan);
},
equals: function(datetime) {
return this.timespan.equals(datetime.timespan);
},
toString : function(format) {
return this._format(!format ? 'yyyy/MM/dd HH:mm:ss.fff' : format);
},
_format: function(format, culture) {
var useCulture = (culture) ? culture : this.culture;
var ret = '', data = this._createFormatData(useCulture);
var regexp = DateTime.regExpFormat;
while(true) {
var l = regexp.lastIndex, arr = regexp.exec(format);
ret += format.slice(l, arr ? arr.index : format.length);
if (!arr) break;
var s = arr[0];
ret += data[s] !== undefined ? data[s] : s;
}
return ret;
},
_createFormatData: function(culture) {
var data = new Array();
var year = this.year(), month = this.month(), day = this.day(), dayOfWeek = this.dayOfWeek(),
hour = this.hour(), minute = this.minute(), second = this.second(), millisecond = this.millisecond();
var strYear = '' + year;
var padLeft0 = function(value) { return _padLeft(value, 2, 0); };
data['dddd'] = culture.dayNames.full[dayOfWeek];
data['ddd'] = culture.dayNames.short[dayOfWeek];
data['dd'] = padLeft0(day);
data['d'] = day;
data['fff'] = _padLeft(millisecond, 3, '0');
data['ff'] = _padLeft(Math.floor(millisecond / 10), 2, '0');
data['f'] = Math.floor(millisecond / 100);
data['hh'] = padLeft0(hour > 12 ? hour - 12 : hour);
data['h'] = hour > 12 ? hour - 12 : hour;
data['HH'] = padLeft0(hour);
data['H'] = hour;
data['mm'] = padLeft0(minute);
data['m'] = minute;
data['MMMM'] = culture.monthNames.full[month - 1];
data['MMM'] = culture.monthNames.short[month - 1];
data['MM'] = padLeft0(month);
data['M'] = month;
data['ss'] = padLeft0(second);
data['s'] = second;
data['tt'] = (hour > 12 ? culture.apNames.full.PM : culture.apNames.full.AM);
data['t'] = (hour > 12 ? culture.apNames.short.PM : culture.apNames.short.AM);
data['yyyy'] = year;
data['yyy'] = year;
data['yy'] = strYear.length > 1 ? strYear.slice(-2) : strYear;
data['y'] = data['yy'];
return data;
},
_ymd2days: function(year, month, day) {
var div = function(x,y){ return Math.floor(x/y); };
var lastYear = year - 1;
var arr = DateTime.isLeapYear(year) ? DateTime.daysMonthLeapYear : DateTime.daysMonth;
var a = div(lastYear, 400),
b = div(lastYear % 400, 100),
c = div(lastYear % 100, 4),
d = lastYear % 4,
e = arr[month - 1] + day - 1;
return (146097 * a) + (36524 * b) + (1461 * c) + (365 * d) + e;
},
// [part] 0:year, 1:dayOfYear, 2:month, 3:day
_span2ymd: function(part) {
// 1/01/01=1days,1/12/31=365day
// 4years=365*4+1 = 1,461days
// 100years=1461*25-1= 36,524days
// 400years=36524*4-1=146,097days
// totalDays = (146,097 * a) + (36,524 * b) + (1,461 * c) + (365 * d) + e
// e = daysMonth + daysThisMont
var div = function(x,y){ return Math.floor(x/y); };
var days = Math.floor(this.timespan.totalDays());
var a = div(days, 146097);
days -= a * 146097;
var b = div(days, 36524);
// 36524*4=146,096 < 146,09
if (b == 4) {
b = 3;
}
days -= b * 36524;
var c = div(days, 1461);
// 1461*25=36525 > 3652
days -= c * 1461;
var d = div(days, 365);
// 365*4=1460 < 146
if (d == 4) {
d = 3;
}
// year
var year = (((((a * 400) + (b * 100)) + (c * 4)) + d) + 1);
if (part == 0) {
return year;
}
// dayOfYea
days -= d * 365;
if (part == 1) {
return (days + 1);
}
// month
var idx = 0, arr = DateTime.isLeapYear(year) ? DateTime.daysMonthLeapYear : DateTime.daysMonth;
while (days >= arr[idx]) {
idx++;
}
if (part == 2) {
return idx;
}
// day
return (days - arr[idx - 1] + 1);
},
/* Properties */
date: function() {
return new DateTime(this.timespan.totalMillisec());
},
day: function() {
return this._span2ymd(3);
},
// 0:sun,1:mon,2:tue,3:wed,4:thu,5:fri,6:sat
dayOfWeek: function() {
return (this.timespan.days() + 1) % 7;
},
dayOfYear: function() {
return this._span2ymd(1);
},
hour: function() {
return this.timespan.hours();
},
millisecond: function() {
return this.timespan.milliseconds();
},
minute: function() {
return this.timespan.minutes();
},
month: function() {
return this._span2ymd(2);
},
second: function() {
return this.timespan.seconds();
},
timeOfDay: function() {
return new TimeSpan(this.timespan.totalMillisec % (1000 * 60 * 60 * 24));
},
totalMilliseconds: function() {
return this.timespan.totalMilliseconds();
},
year: function() {
return this._span2ymd(0);
}
};
/**
* TimeSpan
* new TimeSpan(totalMillisec);
* new TimeSpan(hours,minutes,seconds);
* new TimeSpan(days,hours,minutes,seconds);
* new TimeSpan(days,hours,minutes,seconds,milliseconds);
*/
TimeSpan = function() {
var days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
switch(arguments.length) {
case 1:
milliseconds = arguments[0];
break;
case 3:
hours = arguments[0];
minutes = arguments[1];
seconds = arguments[2];
break;
case 4:
days = arguments[0];
hours = arguments[1];
minutes = arguments[2];
seconds = arguments[3];
break;
case 5:
days = arguments[0];
hours = arguments[1];
minutes = arguments[2];
seconds = arguments[3];
milliseconds = arguments[4];
break;
default:
throw('invalid arguments.');
}
this.totalMillisec = (days * 1000 * 60 * 60 * 24) + (hours * 1000 * 60 * 60) + (minutes * 1000 * 60) + (seconds * 1000) + milliseconds;
};
TimeSpan.prototype = {
/* Methods */
toString: function() {
return (Math.abs(this.days()) ? _padLeft(Math.abs(this.days())) + '.': '') + _padLeft(Math.abs(this.hours())) + ':' + _padLeft(Math.abs(this.minutes())) + ':' + _padLeft(Math.abs(this.seconds())) + '.' + Math.abs(this.milliseconds());
},
compareTo : function(timespan){
if (this.totalMillisec == timespan.totalMillisec) return 0;
return (this.totalMillisec > timespan.totalMillisec) ? 1 : -1;
},
equals: function(timespan) {
return this.compareTo(timespan) == 0;
},
/* Properties */
days: function() {
return this.round(this.totalMillisec / (1000 * 60 * 60 * 24));
},
hours: function() {
return this.round((this.totalMillisec % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
},
minutes: function() {
return this.round((this.totalMillisec % (1000 * 60 * 60)) / (1000 * 60));
},
seconds: function() {
return this.round((this.totalMillisec % (1000 * 60)) / (1000));
},
milliseconds: function() {
return this.round(this.totalMillisec % 1000);
},
totalDays: function() {
return this.totalMillisec / (1000 * 60 * 60 * 24);
},
totalHours: function() {
return this.totalMillisec / (1000 * 60 * 60);
},
totalMinutes: function() {
return this.totalMillisec / (1000 * 60);
},
totalSeconds: function() {
return this.totalMillisec / (1000);
},
totalMilliseconds: function() {
return this.totalMillisec;
},
round: function(value) {
return Math.floor(value);
}
};
_ns.DateTime = DateTime;
_ns.TimeSpan = TimeSpan;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment