break apart date_utils.js

This commit is contained in:
Adam Shaw
2014-02-02 13:07:52 -08:00
parent 3746117815
commit 1f5b6490a3
6 changed files with 514 additions and 489 deletions
+2 -1
View File
@@ -20,7 +20,8 @@
"src/Header.js",
"src/EventManager.js",
"src/util.js",
"src/date_util.js",
"src/moment-ext.js",
"src/date-formatting.js",
"src/basic/MonthView.js",
"src/basic/BasicWeekView.js",
"src/basic/BasicDayView.js",
+214
View File
@@ -0,0 +1,214 @@
// Single Date Formatting
// -------------------------------------------------------------------------------------------------
// call this if you want Moment's original format method to be used
function momentFormat(mom, formatStr) {
return moment.fn.format.call(mom, formatStr);
}
// Formats `date` with a Moment formatting string, but allow our non-zero areas and
// additional token.
function formatDate(date, formatStr) {
return formatDateWithChunks(date, getFormatStringChunks(formatStr));
}
function formatDateWithChunks(date, chunks) {
var s = '';
var i;
for (i=0; i<chunks.length; i++) {
s += formatDateWithChunk(date, chunks[i]);
}
return s;
}
// addition formatting tokens we want recognized
var tokenOverrides = {
t: function(date) { // "a" or "p"
return momentFormat(date, 'a').charAt(0);
},
T: function(date) { // "A" or "P"
return momentFormat(date, 'A').charAt(0);
}
};
function formatDateWithChunk(date, chunk) {
var token;
var maybeStr;
if (typeof chunk === 'string') { // a literal string
return chunk;
}
else if ((token = chunk.token)) { // a token, like "YYYY"
if (tokenOverrides[token]) {
return tokenOverrides[token](date); // use our custom token
}
return momentFormat(date, token);
}
else if (chunk.maybe) { // a grouping of other chunks that must be non-zero
maybeStr = formatDateWithChunks(date, chunk.maybe);
if (maybeStr.match(/[1-9]/)) {
return maybeStr;
}
}
return '';
}
// Date Range Formatting
// -------------------------------------------------------------------------------------------------
// TODO: make it work with timezone offset
// Using a formatting string meant for a single date, generate a range string, like
// "Sep 2 - 9 2013", that intelligently inserts a separator where the dates differ.
// If the dates are the same as far as the format string is concerned, just return a single
// rendering of one date, without any separator.
function formatRange(date1, date2, formatStr, separator, isRTL) {
// Expand localized format strings, like "LL" -> "MMMM D YYYY"
formatStr = date1.lang().longDateFormat(formatStr) || formatStr;
// BTW, this is not important for `formatDate` because it is impossible to put custom tokens
// or non-zero areas in Moment's localized format strings.
separator = separator || ' - ';
return formatRangeWithChunks(
date1,
date2,
getFormatStringChunks(formatStr),
separator,
isRTL
);
}
fc.formatRange = formatRange; // expose
function formatRangeWithChunks(date1, date2, chunks, separator, isRTL) {
var chunkStr; // the rendering of the chunk
var leftI;
var leftStr = '';
var rightI;
var rightStr = '';
var middleI;
var middleStr1 = '';
var middleStr2 = '';
var middleStr = '';
// Start at the leftmost side of the formatting string and continue until you hit a token
// that is not the same between dates.
for (leftI=0; leftI<chunks.length; leftI++) {
chunkStr = formatSimilarChunk(date1, date2, chunks[leftI]);
if (chunkStr === false) {
break;
}
leftStr += chunkStr;
}
// Similarly, start at the rightmost side of the formatting string and move left
for (rightI=chunks.length-1; rightI>leftI; rightI--) {
chunkStr = formatSimilarChunk(date1, date2, chunks[rightI]);
if (chunkStr === false) {
break;
}
rightStr = chunkStr + rightStr;
}
// The area in the middle is different for both of the dates.
// Collect them distinctly so we can jam them together later.
for (middleI=leftI; middleI<=rightI; middleI++) {
middleStr1 += formatDateWithChunk(date1, chunks[middleI]);
middleStr2 += formatDateWithChunk(date2, chunks[middleI]);
}
if (middleStr1 || middleStr2) {
if (isRTL) {
middleStr = middleStr2 + separator + middleStr1;
}
else {
middleStr = middleStr1 + separator + middleStr2;
}
}
return leftStr + middleStr + rightStr;
}
var similarUnitMap = {
Y: 'year',
M: 'month',
D: 'day', // day of month
d: 'day' // day of week
};
// don't go any further than day, because we don't want to break apart times like "12:30:00"
// TODO: week maybe?
// Given a formatting chunk, and given that both dates are similar in the regard the
// formatting chunk is concerned, format date1 against `chunk`. Otherwise, return `false`.
function formatSimilarChunk(date1, date2, chunk) {
var token;
var unit;
if (typeof chunk === 'string') { // a literal string
return chunk;
}
else if ((token = chunk.token)) {
unit = similarUnitMap[token.charAt(0)];
// are the dates the same for this unit of measurement?
if (unit && date1.isSame(date2, unit)) {
return momentFormat(date1, token); // would be the same if we used `date2`
// BTW, don't support custom tokens
}
}
return false; // the chunk is NOT the same for the two dates
// BTW, don't support splitting on non-zero areas
}
// Chunking Utils
// -------------------------------------------------------------------------------------------------
var formatStringChunkCache = {};
function getFormatStringChunks(formatStr) {
if (formatStr in formatStringChunkCache) {
return formatStringChunkCache[formatStr];
}
return (formatStringChunkCache[formatStr] = chunkFormatString(formatStr));
}
// Break the formatting string into an array of chunks
function chunkFormatString(formatStr) {
var chunks = [];
var chunker = /\[([^\]]*)\]|\(([^\)]*)\)|((\w)\4*o?T?)|([^\w\[\(]+)/g; // TODO: more descrimination
var match;
while ((match = chunker.exec(formatStr))) {
if (match[1]) { // a literal string instead [ ... ]
chunks.push(match[1]);
}
else if (match[2]) { // non-zero formatting inside ( ... )
chunks.push({ maybe: chunkFormatString(match[2]) });
}
else if (match[3]) { // a formatting token
chunks.push({ token: match[3] });
}
else if (match[5]) { // an unenclosed literal string
chunks.push(match[5]);
}
}
return chunks;
}
-487
View File
@@ -1,487 +0,0 @@
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
var ambigTimeRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))$/;
var ambigZoneRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/;
var momentCloneMethod = moment.fn.clone;
var momentFormatMethod = moment.fn.format;
var momentToISOStringMethod = moment.fn.toISOString;
// diffs the two moments into a Duration where full-days are recorded first,
// then the remaining time.
function dayishDiff(d1, d0) {
return moment.duration({
days: d1.clone().stripTime().diff(d0.clone().stripTime(), 'days'),
ms: d1.time() - d0.time()
});
}
function isNativeDate(input) {
return Object.prototype.toString.call(input) === '[object Date]' ||
input instanceof Date;
}
// MOMENT: creating
// -------------------------------------------------------------------------------------------------
// Creates a moment in the local timezone, similar to the vanilla moment(...) constructor,
// but with extra features:
// - ambiguous times
// - enhanced formatting (TODO)
fc.moment = function() {
return buildMoment(arguments);
};
// Sames as fc.moment, but creates a moment in the UTC timezone.
fc.moment.utc = function() {
return buildMoment(arguments, true);
};
// Creates a moment and preserves the timezone offset of the ISO8601 string,
// allowing for ambigous timezones. If the string is not an ISO8601 string,
// the moment is processed in UTC-mode (a departure from moment's method).
fc.moment.parseZone = function() {
return buildMoment(arguments, true, true);
};
// when parseZone==true, if can't figure it out, fall back to parseUTC
function buildMoment(args, parseUTC, parseZone) {
var isSingleArg = args.length == 1;
var isSingleMoment = isSingleArg && moment.isMoment(args[0]);
var isSingleString = isSingleArg && typeof args[0] === 'string';
var isSingleArray = isSingleArg && $.isArray(args[0]);
var isSingleNativeDate = isSingleArg && isNativeDate(args[0]);
var isAmbigTime = isSingleString && ambigTimeRegex.test(args[0]);
var isAmbigZone = isAmbigTime || isSingleArray || isSingleString && ambigZoneRegex.test(args[0]);
var mom;
if (parseUTC || parseZone || isAmbigTime) {
mom = moment.utc.apply(moment, args);
}
else {
mom = moment.apply(null, args);
}
// if we are essentially cloning a moment, transfer over existing _ambig properties
if (isSingleMoment) {
transferAmbigs(args[0], mom);
}
if (isAmbigTime) {
mom._ambigTime = true;
mom._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
}
if (parseZone) {
if (isAmbigZone) {
mom._ambigZone = true;
}
else if (isSingleString) {
mom.zone(args[0]); // if fails, will set it to 0, which it already was
}
else if (isSingleNativeDate || args[0] === undefined) {
// native Date object?
// specified with no arguments?
// then consider the moment to be local
mom.local();
}
}
mom._fc = true; // flag for use other extended functionality (only formatting at this point)
return mom;
}
// we need to patch moment's clone method because it will not copy our _ambig properties
moment.fn.clone = function() {
var res = momentCloneMethod.apply(this, arguments);
transferAmbigs(this, res);
return res;
};
// transfers our internal _ambig properties from one moment to another, but only if true
function transferAmbigs(srcMoment, destMoment) {
if (srcMoment._ambigTime) {
destMoment._ambigTime = true;
}
if (srcMoment._ambigZone) {
destMoment._ambigZone = true;
}
}
// MOMENT: time-of-day
// -------------------------------------------------------------------------------------------------
// GETTER
// Returns a Duration with the hours/minutes/seconds/ms values of the moment.
// If the moment has an ambiguous time, a duration of 00:00 will be returned.
//
// SETTER
// You can supply a Duration, a Moment, or a Duration-like argument.
// When setting the time, and the moment has an ambiguous time, it then becomes unambiguous.
moment.fn.time = function(time) {
if (time === undefined) { // getter
return moment.duration({
hours: this.hours(),
minutes: this.minutes(),
seconds: this.seconds(),
milliseconds: this.milliseconds()
});
}
else { // setter
delete this._ambigTime; // mark that the moment now has a time
if (!moment.isDuration(time) && !moment.isMoment(time)) {
time = moment.duration(time);
}
return this.hours(time.hours() + time.days() * 24) // day value will cause overflow (so 24 hours becomes 00:00:00 of next day)
.minutes(time.minutes())
.seconds(time.seconds())
.milliseconds(time.milliseconds());
}
};
// Converts the moment to UTC, stripping out its time-of-day and timezone offset,
// but preserving its YMD. A moment with a stripped time will display no time
// nor timezone offset when .format() is called.
moment.fn.stripTime = function() {
var a = this.toArray(); // year,month,date,hours,minutes,seconds as an array
this._ambigTime = true;
this._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
return this.utc()
.year(a[0])
.month(a[1])
.date(a[2])
.hours(0)
.minutes(0)
.seconds(0)
.milliseconds(0);
};
// Returns if the moment has a non-ambiguous time (boolean)
moment.fn.hasTime = function() {
return !this._ambigTime;
};
// MOMENT: timezone offset
// -------------------------------------------------------------------------------------------------
// Converts the moment to UTC, stripping out its timezone offset, but preserving its
// YMD and time-of-day. A moment with a stripped timezone offset will display no
// timezone offset when .format() is called.
moment.fn.stripZone = function() {
var a = this.toArray(); // year,month,date,hours,minutes,seconds as an array
this._ambigZone = true;
return this.utc()
.year(a[0])
.month(a[1])
.date(a[2])
.hours(a[3])
.minutes(a[4])
.seconds(a[5])
.milliseconds(a[6]);
};
// Returns of the moment has a non-ambiguous timezone offset (boolean)
moment.fn.hasZone = function() {
return !this._ambigZone;
};
// MOMENT: formatting mods
// -------------------------------------------------------------------------------------------------
moment.fn.format = function() {
if (!arguments[0]) {
if (this._ambigTime) {
return momentFormat(this, 'YYYY-MM-DD');
}
if (this._ambigZone) {
return momentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');
}
}
if (this._fc) {
return formatDate(this, arguments[0]); // our extended formatting
}
else {
return momentFormatMethod.apply(this, arguments); // pass along all arguments
}
};
moment.fn.toISOString = function() {
if (this._ambigTime) {
return momentFormat(this, 'YYYY-MM-DD');
}
if (this._ambigZone) {
return momentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');
}
return momentToISOStringMethod.apply(this, arguments); // pass along all arguments
};
// call this if you want Moment's original format method to be used
function momentFormat(moment, formatStr) {
return momentFormatMethod.call(moment, formatStr);
}
// MOMENT: misc utils
// -------------------------------------------------------------------------------------------------
// Is the moment within the specified range? `end` is exclusive.
// TODO: rename for collision reasons?
moment.fn.isWithin = function(start, end) {
return this >= moment(start) && this < moment(end);
};
$.each([
'isBefore',
'isAfter',
//'isSame', // nevermind. moment handles normalization to UTC
'isWithin'
], function(i, methodName) {
var origMethod = moment.fn[methodName];
var momentCount = methodName == 'isWithin' ? 2 : 1;
moment.fn[methodName] = function() {
var newThis;
var args = Array.prototype.slice.call(arguments);
var i;
if (this._ambigZone) {
for (i=0; i<momentCount; i++) {
if (typeof args[i] === 'string') {
args[i] = fc.moment.parseZone(args[i]);
}
}
}
for (i=0; i<momentCount; i++) {
if (moment.isMoment(args[i]) && args[i]._ambigZone !== this._ambigZone) {
newThis = newThis || this.clone().stripZone();
args[i] = args[i].clone().stripZone();
}
}
return origMethod.apply(newThis || this, args);
};
});
// Single Date Formatting
// -------------------------------------------------------------------------------------------------
// Formats `date` with a Moment formatting string, but allow our non-zero areas and
// additional token.
function formatDate(date, formatStr) {
return formatDateWithChunks(date, getFormatStringChunks(formatStr));
}
function formatDateWithChunks(date, chunks) {
var s = '';
var i;
for (i=0; i<chunks.length; i++) {
s += formatDateWithChunk(date, chunks[i]);
}
return s;
}
// addition formatting tokens we want recognized
var tokenOverrides = {
t: function(date) { // "a" or "p"
return momentFormat(date, 'a').charAt(0);
},
T: function(date) { // "A" or "P"
return momentFormat(date, 'A').charAt(0);
}
};
function formatDateWithChunk(date, chunk) {
var token;
var maybeStr;
if (typeof chunk === 'string') { // a literal string
return chunk;
}
else if ((token = chunk.token)) { // a token, like "YYYY"
if (tokenOverrides[token]) {
return tokenOverrides[token](date); // use our custom token
}
return momentFormat(date, token);
}
else if (chunk.maybe) { // a grouping of other chunks that must be non-zero
maybeStr = formatDateWithChunks(date, chunk.maybe);
if (maybeStr.match(/[1-9]/)) {
return maybeStr;
}
}
return '';
}
// Date Range Formatting
// -------------------------------------------------------------------------------------------------
// TODO: make it work with timezone offset
// Using a formatting string meant for a single date, generate a range string, like
// "Sep 2 - 9 2013", that intelligently inserts a separator where the dates differ.
// If the dates are the same as far as the format string is concerned, just return a single
// rendering of one date, without any separator.
function formatRange(date1, date2, formatStr, separator, isRTL) {
// Expand localized format strings, like "LL" -> "MMMM D YYYY"
formatStr = date1.lang().longDateFormat(formatStr) || formatStr;
// BTW, this is not important for `formatDate` because it is impossible to put custom tokens
// or non-zero areas in Moment's localized format strings.
separator = separator || ' - ';
return formatRangeWithChunks(
date1,
date2,
getFormatStringChunks(formatStr),
separator,
isRTL
);
}
fc.formatRange = formatRange; // expose
function formatRangeWithChunks(date1, date2, chunks, separator, isRTL) {
var chunkStr; // the rendering of the chunk
var leftI;
var leftStr = '';
var rightI;
var rightStr = '';
var middleI;
var middleStr1 = '';
var middleStr2 = '';
var middleStr = '';
// Start at the leftmost side of the formatting string and continue until you hit a token
// that is not the same between dates.
for (leftI=0; leftI<chunks.length; leftI++) {
chunkStr = formatSimilarChunk(date1, date2, chunks[leftI]);
if (chunkStr === false) {
break;
}
leftStr += chunkStr;
}
// Similarly, start at the rightmost side of the formatting string and move left
for (rightI=chunks.length-1; rightI>leftI; rightI--) {
chunkStr = formatSimilarChunk(date1, date2, chunks[rightI]);
if (chunkStr === false) {
break;
}
rightStr = chunkStr + rightStr;
}
// The area in the middle is different for both of the dates.
// Collect them distinctly so we can jam them together later.
for (middleI=leftI; middleI<=rightI; middleI++) {
middleStr1 += formatDateWithChunk(date1, chunks[middleI]);
middleStr2 += formatDateWithChunk(date2, chunks[middleI]);
}
if (middleStr1 || middleStr2) {
if (isRTL) {
middleStr = middleStr2 + separator + middleStr1;
}
else {
middleStr = middleStr1 + separator + middleStr2;
}
}
return leftStr + middleStr + rightStr;
}
var similarUnitMap = {
Y: 'year',
M: 'month',
D: 'day', // day of month
d: 'day' // day of week
};
// don't go any further than day, because we don't want to break apart times like "12:30:00"
// TODO: week maybe?
// Given a formatting chunk, and given that both dates are similar in the regard the
// formatting chunk is concerned, format date1 against `chunk`. Otherwise, return `false`.
function formatSimilarChunk(date1, date2, chunk) {
var token;
var unit;
if (typeof chunk === 'string') { // a literal string
return chunk;
}
else if ((token = chunk.token)) {
unit = similarUnitMap[token.charAt(0)];
// are the dates the same for this unit of measurement?
if (unit && date1.isSame(date2, unit)) {
return momentFormat(date1, token); // would be the same if we used `date2`
// BTW, don't support custom tokens
}
}
return false; // the chunk is NOT the same for the two dates
// BTW, don't support splitting on non-zero areas
}
// Chunking Utils
// -------------------------------------------------------------------------------------------------
var formatStringChunkCache = {};
function getFormatStringChunks(formatStr) {
if (formatStr in formatStringChunkCache) {
return formatStringChunkCache[formatStr];
}
return (formatStringChunkCache[formatStr] = chunkFormatString(formatStr));
}
// Break the formatting string into an array of chunks
function chunkFormatString(formatStr) {
var chunks = [];
var chunker = /\[([^\]]*)\]|\(([^\)]*)\)|((\w)\4*o?T?)|([^\w\[\(]+)/g; // TODO: more descrimination
var match;
while ((match = chunker.exec(formatStr))) {
if (match[1]) { // a literal string instead [ ... ]
chunks.push(match[1]);
}
else if (match[2]) { // non-zero formatting inside ( ... )
chunks.push({ maybe: chunkFormatString(match[2]) });
}
else if (match[3]) { // a formatting token
chunks.push({ token: match[3] });
}
else if (match[5]) { // an unenclosed literal string
chunks.push(match[5]);
}
}
return chunks;
}
+264
View File
@@ -0,0 +1,264 @@
var ambigTimeRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))$/;
var ambigZoneRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/;
// MOMENT: creating
// -------------------------------------------------------------------------------------------------
// Creates a moment in the local timezone, similar to the vanilla moment(...) constructor,
// but with extra features:
// - ambiguous times
// - enhanced formatting (TODO)
fc.moment = function() {
return makeMoment(arguments);
};
// Sames as fc.moment, but creates a moment in the UTC timezone.
fc.moment.utc = function() {
return makeMoment(arguments, true);
};
// Creates a moment and preserves the timezone offset of the ISO8601 string,
// allowing for ambigous timezones. If the string is not an ISO8601 string,
// the moment is processed in UTC-mode (a departure from moment's method).
fc.moment.parseZone = function() {
return makeMoment(arguments, true, true);
};
function FCMoment(config) {
extend(this, config);
}
FCMoment.prototype = createObject(moment.fn);
FCMoment.prototype.clone = function() {
return makeMoment([ this ]);
};
// when parseZone==true, if can't figure it out, fall back to parseUTC
function makeMoment(args, parseUTC, parseZone) {
var isSingleArg = args.length == 1;
var isSingleMoment = isSingleArg && moment.isMoment(args[0]);
var isSingleString = isSingleArg && typeof args[0] === 'string';
var isSingleArray = isSingleArg && $.isArray(args[0]);
var isSingleNativeDate = isSingleArg && isNativeDate(args[0]);
var isAmbigTime = isSingleString && ambigTimeRegex.test(args[0]);
var isAmbigZone = isAmbigTime || isSingleArray || isSingleString && ambigZoneRegex.test(args[0]);
var mom;
if (parseUTC || parseZone || isAmbigTime) {
mom = moment.utc.apply(moment, args);
}
else {
mom = moment.apply(null, args);
}
if (isSingleMoment) {
transferAmbigs(args[0], mom);
}
if (isAmbigTime) {
mom._ambigTime = true;
mom._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
}
if (parseZone) {
if (isAmbigZone) {
mom._ambigZone = true;
}
else if (isSingleString) {
mom.zone(args[0]); // if fails, will set it to 0, which it already was
}
else if (isSingleNativeDate || args[0] === undefined) {
// native Date object?
// specified with no arguments?
// then consider the moment to be local
mom.local();
}
}
return new FCMoment(mom);
}
// transfers our internal _ambig properties from one moment to another
function transferAmbigs(src, dest) {
if (src._ambigTime) {
dest._ambigTime = true;
}
else if (dest._ambigTime) {
delete dest._ambigTime;
}
if (src._ambigZone) {
dest._ambigZone = true;
}
else if (dest._ambigZone) {
delete dest._ambigZone;
}
}
function makeMomentAs(input, model) {
var output = fc.moment(input);
if (model._ambigTime) {
output.stripTime();
}
else if (model._ambigZone) {
output.stripZone();
}
return output;
}
// MOMENT: time-of-day
// -------------------------------------------------------------------------------------------------
// GETTER
// Returns a Duration with the hours/minutes/seconds/ms values of the moment.
// If the moment has an ambiguous time, a duration of 00:00 will be returned.
//
// SETTER
// You can supply a Duration, a Moment, or a Duration-like argument.
// When setting the time, and the moment has an ambiguous time, it then becomes unambiguous.
FCMoment.prototype.time = function(time) {
if (time === undefined) { // getter
return moment.duration({
hours: this.hours(),
minutes: this.minutes(),
seconds: this.seconds(),
milliseconds: this.milliseconds()
});
}
else { // setter
delete this._ambigTime; // mark that the moment now has a time
if (!moment.isDuration(time) && !moment.isMoment(time)) {
time = moment.duration(time);
}
return this.hours(time.hours() + time.days() * 24) // day value will cause overflow (so 24 hours becomes 00:00:00 of next day)
.minutes(time.minutes())
.seconds(time.seconds())
.milliseconds(time.milliseconds());
}
};
// Converts the moment to UTC, stripping out its time-of-day and timezone offset,
// but preserving its YMD. A moment with a stripped time will display no time
// nor timezone offset when .format() is called.
FCMoment.prototype.stripTime = function() {
var a = this.toArray(); // year,month,date,hours,minutes,seconds as an array
this._ambigTime = true;
this._ambigZone = true; // if ambiguous time, also ambiguous timezone offset
return this.utc()
.year(a[0])
.month(a[1])
.date(a[2])
.hours(0)
.minutes(0)
.seconds(0)
.milliseconds(0);
};
// Returns if the moment has a non-ambiguous time (boolean)
FCMoment.prototype.hasTime = function() {
return !this._ambigTime;
};
// MOMENT: timezone offset
// -------------------------------------------------------------------------------------------------
// Converts the moment to UTC, stripping out its timezone offset, but preserving its
// YMD and time-of-day. A moment with a stripped timezone offset will display no
// timezone offset when .format() is called.
FCMoment.prototype.stripZone = function() {
var a = this.toArray(); // year,month,date,hours,minutes,seconds as an array
this._ambigZone = true;
return this.utc()
.year(a[0])
.month(a[1])
.date(a[2])
.hours(a[3])
.minutes(a[4])
.seconds(a[5])
.milliseconds(a[6]);
};
// Returns of the moment has a non-ambiguous timezone offset (boolean)
FCMoment.prototype.hasZone = function() {
return !this._ambigZone;
};
FCMoment.prototype.zone = function(tzo) {
if (tzo != undefined) {
this._ambigZone = false;
}
return moment.fn.zone.apply(this, arguments);
};
FCMoment.prototype.local = function() {
this._ambigZone = false;
return moment.fn.local.apply(this, arguments);
};
FCMoment.prototype.utc = function() {
this._ambigZone = false;
return moment.fn.utc.apply(this, arguments);
};
// MOMENT: formatting mods
// -------------------------------------------------------------------------------------------------
FCMoment.prototype.format = function() {
if (arguments[0]) {
return formatDate(this, arguments[0]); // our extended formatting
}
if (this._ambigTime) {
return momentFormat(this, 'YYYY-MM-DD');
}
if (this._ambigZone) {
return momentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');
}
return momentFormat(this); // default moment original formatting
};
FCMoment.prototype.toISOString = function() {
if (this._ambigTime) {
return momentFormat(this, 'YYYY-MM-DD');
}
if (this._ambigZone) {
return momentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');
}
return moment.fn.toISOString.apply(this, arguments);
};
// MOMENT: misc utils
// -------------------------------------------------------------------------------------------------
// Is the moment within the specified range? `end` is exclusive.
FCMoment.prototype.isWithin = function(start, end) {
return this >= makeMomentAs(start, this) && this < makeMomentAs(end, this);
};
$.each([
'isBefore',
'isAfter'
], function(i, methodName) {
FCMoment.prototype[methodName] = function(input, units) {
moment.fn[methodName].call(
this,
makeMomentAs(input, this),
units
);
};
});
+31
View File
@@ -9,6 +9,37 @@ function createObject(proto) { // like Object.create
return new f();
}
function extend(a, b) {
for (var i in b) {
if (b.hasOwnProperty(i)) {
a[i] = b[i];
}
}
}
/* Date
-----------------------------------------------------------------------------*/
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
// diffs the two moments into a Duration where full-days are recorded first,
// then the remaining time.
function dayishDiff(d1, d0) {
return moment.duration({
days: d1.clone().stripTime().diff(d0.clone().stripTime(), 'days'),
ms: d1.time() - d0.time()
});
}
function isNativeDate(input) {
return Object.prototype.toString.call(input) === '[object Date]' ||
input instanceof Date;
}
+3 -1
View File
@@ -5,7 +5,9 @@
<script src='../lib/moment/moment.js'></script>
<script src='../lib/moment/min/langs.min.js'></script>
<script>fc = {}</script>
<script src='../src/date_util.js'></script>
<script src='../src/util.js'></script>
<script src='../src/moment-ext.js'></script>
<script src='../src/date-formatting.js'></script>
</head>
<body>
</body>