Last active
September 28, 2015 21:38
-
-
Save myaumyau/1500087 to your computer and use it in GitHub Desktop.
[js]DateTime.js
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
(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