Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide masks DDD and DDDD to print "Yesterday", "Today" or "Tomorrow". #71

Merged
merged 12 commits into from
Dec 22, 2020
2 changes: 2 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ dateFormat(now, "N");
| `d` | Day of the month as digits; no leading zero for single-digit days. |
| `dd` | Day of the month as digits; leading zero for single-digit days. |
| `ddd` | Day of the week as a three-letter abbreviation. |
| `DDD` | "Yesterday", "Today" or "Tomorrow" if date lies within these three days. Else fall back to ddd. |
chase-manning marked this conversation as resolved.
Show resolved Hide resolved
| `dddd` | Day of the week as its full name. |
| `DDDD` | "Yesterday", "Today" or "Tomorrow" if date lies within these three days. Else fall back to dddd. |
| `m` | Month as digits; no leading zero for single-digit months. |
| `mm` | Month as digits; leading zero for single-digit months. |
| `mmm` | Month as a three-letter abbreviation. |
Expand Down
255 changes: 255 additions & 0 deletions lib/dateformat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
/*
chase-manning marked this conversation as resolved.
Show resolved Hide resolved
* Date Format 1.2.3
* (c) 2007-2009 Steven Levithan <stevenlevithan.com>
* MIT license
*
* Includes enhancements by Scott Trenda <scott.trenda.net>
* and Kris Kowal <cixar.com/~kris.kowal/>
*
* Accepts a date, a mask, or a date and a mask.
* Returns a formatted version of the given date.
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
*/

(function(global) {
'use strict';

var dateFormat = (function() {
var token = /d{1,4}|D{3,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWN]|'[^']*'|'[^']*'/g;
var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g;
var timezoneClip = /[^-+\dA-Z]/g;

// Regexes and supporting functions are cached through closure
return function (date, mask, utc, gmt) {

// You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
if (arguments.length === 1 && kindOf(date) === 'string' && !/\d/.test(date)) {
mask = date;
date = undefined;
}

date = date || new Date;

if(!(date instanceof Date)) {
date = new Date(date);
}

if (isNaN(date)) {
throw TypeError('Invalid date');
}

mask = String(dateFormat.masks[mask] || mask || dateFormat.masks['default']);

// Allow setting the utc/gmt argument via the mask
var maskSlice = mask.slice(0, 4);
if (maskSlice === 'UTC:' || maskSlice === 'GMT:') {
mask = mask.slice(4);
utc = true;
if (maskSlice === 'GMT:') {
gmt = true;
}
}

var _ = utc ? 'getUTC' : 'get';
var d = date[_ + 'Date']();
var D = date[_ + 'Day']();
var m = date[_ + 'Month']();
var y = date[_ + 'FullYear']();
var Q = (function(){
var today = new Date();
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
var today_d = today[_ + 'Date']();
var today_m = today[_ + 'Month']();
var today_y = today[_ + 'FullYear']();
var yesterday_d = yesterday[_ + 'Date']();
var yesterday_m = yesterday[_ + 'Month']();
var yesterday_y = yesterday[_ + 'FullYear']();
var tomorrow_d = tomorrow[_ + 'Date']();
var tomorrow_m = tomorrow[_ + 'Month']();
var tomorrow_y = tomorrow[_ + 'FullYear']();
var q = undefined;
if(today_y == y && today_m == m && today_d == d){
q = "Today";
}
else if(tomorrow_y == y && tomorrow_m == m && tomorrow_d == d){
q = "Tomorrow";
}
else if(yesterday_y == y && yesterday_m == m && yesterday_d == d){
q = "Yesterday";
}
return q;
})();
var H = date[_ + 'Hours']();
var M = date[_ + 'Minutes']();
var s = date[_ + 'Seconds']();
var L = date[_ + 'Milliseconds']();
var o = utc ? 0 : date.getTimezoneOffset();
var W = getWeek(date);
var N = getDayOfWeek(date);
var flags = {
d: d,
dd: pad(d),
ddd: dateFormat.i18n.dayNames[D],
DDD: Q || dateFormat.i18n.dayNames[D],
dddd: dateFormat.i18n.dayNames[D + 7],
DDDD: Q || dateFormat.i18n.dayNames[D + 7],
m: m + 1,
mm: pad(m + 1),
mmm: dateFormat.i18n.monthNames[m],
mmmm: dateFormat.i18n.monthNames[m + 12],
yy: String(y).slice(2),
yyyy: y,
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(Math.round(L / 10)),
t: H < 12 ? 'a' : 'p',
tt: H < 12 ? 'am' : 'pm',
T: H < 12 ? 'A' : 'P',
TT: H < 12 ? 'AM' : 'PM',
Z: gmt ? 'GMT' : utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''),
o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10],
W: W,
N: N
};

return mask.replace(token, function (match) {
if (match in flags) {
return flags[match];
}
return match.slice(1, match.length - 1);
});
};
})();

dateFormat.masks = {
'default': 'ddd mmm dd yyyy HH:MM:ss',
'shortDate': 'm/d/yy',
'mediumDate': 'mmm d, yyyy',
'longDate': 'mmmm d, yyyy',
'fullDate': 'dddd, mmmm d, yyyy',
'shortTime': 'h:MM TT',
'mediumTime': 'h:MM:ss TT',
'longTime': 'h:MM:ss TT Z',
'isoDate': 'yyyy-mm-dd',
'isoTime': 'HH:MM:ss',
'isoDateTime': 'yyyy-mm-dd\'T\'HH:MM:sso',
'isoUtcDateTime': 'UTC:yyyy-mm-dd\'T\'HH:MM:ss\'Z\'',
'expiresHeaderFormat': 'ddd, dd mmm yyyy HH:MM:ss Z'
};

// Internationalization strings
dateFormat.i18n = {
dayNames: [
'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat',
'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
],
monthNames: [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
]
};

function pad(val, len) {
val = String(val);
len = len || 2;
while (val.length < len) {
val = '0' + val;
}
return val;
}

/**
* Get the ISO 8601 week number
* Based on comments from
* http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
*
* @param {Object} `date`
* @return {Number}
*/
function getWeek(date) {
// Remove time components of date
var targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate());

// Change date to Thursday same week
targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3);

// Take January 4th as it is always in week 1 (see ISO 8601)
var firstThursday = new Date(targetThursday.getFullYear(), 0, 4);

// Change date to Thursday same week
firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3);

// Check if daylight-saving-time-switch occurred and correct for it
var ds = targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset();
targetThursday.setHours(targetThursday.getHours() - ds);

// Number of weeks between target Thursday and first Thursday
var weekDiff = (targetThursday - firstThursday) / (86400000*7);
return 1 + Math.floor(weekDiff);
}

/**
* Get ISO-8601 numeric representation of the day of the week
* 1 (for Monday) through 7 (for Sunday)
*
* @param {Object} `date`
* @return {Number}
*/
function getDayOfWeek(date) {
var dow = date.getDay();
if(dow === 0) {
dow = 7;
}
return dow;
}

/**
* kind-of shortcut
* @param {*} val
* @return {String}
*/
function kindOf(val) {
if (val === null) {
return 'null';
}

if (val === undefined) {
return 'undefined';
}

if (typeof val !== 'object') {
return typeof val;
}

if (Array.isArray(val)) {
return 'array';
}

return {}.toString.call(val)
.slice(8, -1).toLowerCase();
};



if (typeof define === 'function' && define.amd) {
define(function () {
return dateFormat;
});
} else if (typeof exports === 'object') {
module.exports = dateFormat;
} else {
global.dateFormat = dateFormat;
}
})(this);
77 changes: 77 additions & 0 deletions test/test_threedays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
var assert = require('assert');

var dateFormat = require('./../lib/dateformat');

var dayNamesShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
var dayNamesLong = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var threeDays = ['Yesterday', 'Today', 'Tomorrow'];

describe('threeDays', function() {
var date, DDD, DDDD;
beforeEach(function() {
date = new Date();
});
it('should return "Yesterday" (Today - 1 day)', function(done) {
date.setDate(date.getDate() - 1);
DDD = dateFormat(date, 'DDD');
DDDD = dateFormat(date, 'DDDD');
assert.strictEqual(DDD, "Yesterday");
assert.strictEqual(DDDD, "Yesterday");
done();
});
it('should return "Today" (Today)', function(done) {
DDD = dateFormat(date, 'DDD');
DDDD = dateFormat(date, 'DDDD');
assert.strictEqual(DDD, "Today");
assert.strictEqual(DDDD, "Today");
done();
});
it('should return "Tomorrow" (Today + 1 day)', function(done) {
date.setDate(date.getDate() + 1);
DDD = dateFormat(date, 'DDD');
DDDD = dateFormat(date, 'DDDD');
assert.strictEqual(DDD, "Tomorrow");
assert.strictEqual(DDDD, "Tomorrow");
done();
});
it('should not return "Yesterday", "Today" or "Tomorrow" (Today - 2 days)', function(done) {
date.setDate(date.getDate() - 2);
DDD = dateFormat(date, 'DDD');
DDDD = dateFormat(date, 'DDDD');
assert.strictEqual(threeDays.indexOf(DDD), -1);
assert.strictEqual(threeDays.indexOf(DDDD), -1);
done();
});
it('should not return "Yesterday", "Today" or "Tomorrow" (Today + 2 days)', function(done) {
date.setDate(date.getDate() + 2);
DDD = dateFormat(date, 'DDD');
DDDD = dateFormat(date, 'DDDD');
assert.strictEqual(threeDays.indexOf(DDD), -1);
assert.strictEqual(threeDays.indexOf(DDDD), -1);
done();
});
it('should return short day name (Today - 2 days)', function(done) {
date.setDate(date.getDate() - 2);
DDD = dateFormat(date, 'DDD');
assert.notStrictEqual(dayNamesShort.indexOf(DDD), -1);
done();
});
it('should return short day name (Today + 2 days)', function(done) {
date.setDate(date.getDate() + 2);
DDD = dateFormat(date, 'DDD');
assert.notStrictEqual(dayNamesShort.indexOf(DDD), -1);
done();
});
it('should return long day name (Today - 2 days)', function(done) {
date.setDate(date.getDate() - 2);
DDDD = dateFormat(date, 'DDDD');
assert.notStrictEqual(dayNamesLong.indexOf(DDDD), -1);
done();
});
it('should return short day name (Today + 2 days)', function(done) {
date.setDate(date.getDate() + 2);
DDDD = dateFormat(date, 'DDDD');
assert.notStrictEqual(dayNamesLong.indexOf(DDDD), -1);
done();
});
});