date-format 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +138 -82
- package/package.json +3 -3
- package/test/parse-test.js +104 -66
package/lib/index.js
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
|
1
|
+
"use strict";
|
2
2
|
|
3
3
|
function padWithZeros(vNumber, width) {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
var numAsString = vNumber.toString();
|
5
|
+
while (numAsString.length < width) {
|
6
|
+
numAsString = "0" + numAsString;
|
7
|
+
}
|
8
|
+
return numAsString;
|
9
9
|
}
|
10
10
|
|
11
11
|
function addZero(vNumber) {
|
12
|
-
|
12
|
+
return padWithZeros(vNumber, 2);
|
13
13
|
}
|
14
14
|
|
15
15
|
/**
|
@@ -18,108 +18,164 @@ function addZero(vNumber) {
|
|
18
18
|
* @private
|
19
19
|
*/
|
20
20
|
function offset(timezoneOffset) {
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
21
|
+
var os = Math.abs(timezoneOffset);
|
22
|
+
var h = String(Math.floor(os / 60));
|
23
|
+
var m = String(os % 60);
|
24
|
+
if (h.length === 1) {
|
25
|
+
h = "0" + h;
|
26
|
+
}
|
27
|
+
if (m.length === 1) {
|
28
|
+
m = "0" + m;
|
29
|
+
}
|
30
|
+
return timezoneOffset < 0 ? "+" + h + m : "-" + h + m;
|
31
31
|
}
|
32
32
|
|
33
33
|
function datePart(date, displayUTC, part) {
|
34
|
-
return displayUTC ? date[
|
34
|
+
return displayUTC ? date["getUTC" + part]() : date["get" + part]();
|
35
35
|
}
|
36
36
|
|
37
37
|
function asString(format, date) {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
if (typeof format !== "string") {
|
39
|
+
date = format;
|
40
|
+
format = module.exports.ISO8601_FORMAT;
|
41
|
+
}
|
42
|
+
if (!date) {
|
43
|
+
date = module.exports.now();
|
44
|
+
}
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
46
|
+
var displayUTC = format.indexOf("O") > -1;
|
47
|
+
|
48
|
+
var vDay = addZero(datePart(date, displayUTC, "Date"));
|
49
|
+
var vMonth = addZero(datePart(date, displayUTC, "Month") + 1);
|
50
|
+
var vYearLong = addZero(datePart(date, displayUTC, "FullYear"));
|
51
|
+
var vYearShort = addZero(vYearLong.substring(2, 4));
|
52
|
+
var vYear = format.indexOf("yyyy") > -1 ? vYearLong : vYearShort;
|
53
|
+
var vHour = addZero(datePart(date, displayUTC, "Hours"));
|
54
|
+
var vMinute = addZero(datePart(date, displayUTC, "Minutes"));
|
55
|
+
var vSecond = addZero(datePart(date, displayUTC, "Seconds"));
|
56
|
+
var vMillisecond = padWithZeros(
|
57
|
+
datePart(date, displayUTC, "Milliseconds"),
|
58
|
+
3
|
59
|
+
);
|
60
|
+
var vTimeZone = offset(date.getTimezoneOffset());
|
61
|
+
var formatted = format
|
62
|
+
.replace(/dd/g, vDay)
|
63
|
+
.replace(/MM/g, vMonth)
|
64
|
+
.replace(/y{1,4}/g, vYear)
|
65
|
+
.replace(/hh/g, vHour)
|
66
|
+
.replace(/mm/g, vMinute)
|
67
|
+
.replace(/ss/g, vSecond)
|
68
|
+
.replace(/SSS/g, vMillisecond)
|
69
|
+
.replace(/O/g, vTimeZone);
|
70
|
+
return formatted;
|
68
71
|
}
|
69
72
|
|
70
|
-
function extractDateParts(pattern, str) {
|
73
|
+
function extractDateParts(pattern, str, missingValuesDate) {
|
71
74
|
var matchers = [
|
72
|
-
{
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
{
|
80
|
-
|
81
|
-
|
75
|
+
{
|
76
|
+
pattern: /y{1,4}/,
|
77
|
+
regexp: "\\d{1,4}",
|
78
|
+
fn: function(date, value) {
|
79
|
+
date.setFullYear(value);
|
80
|
+
}
|
81
|
+
},
|
82
|
+
{
|
83
|
+
pattern: /MM/,
|
84
|
+
regexp: "\\d{1,2}",
|
85
|
+
fn: function(date, value) {
|
86
|
+
date.setMonth(value - 1);
|
82
87
|
}
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
88
|
+
},
|
89
|
+
{
|
90
|
+
pattern: /dd/,
|
91
|
+
regexp: "\\d{1,2}",
|
92
|
+
fn: function(date, value) {
|
93
|
+
date.setDate(value);
|
94
|
+
}
|
95
|
+
},
|
96
|
+
{
|
97
|
+
pattern: /hh/,
|
98
|
+
regexp: "\\d{1,2}",
|
99
|
+
fn: function(date, value) {
|
100
|
+
date.setHours(value);
|
101
|
+
}
|
102
|
+
},
|
103
|
+
{
|
104
|
+
pattern: /mm/,
|
105
|
+
regexp: "\\d\\d",
|
106
|
+
fn: function(date, value) {
|
107
|
+
date.setMinutes(value);
|
108
|
+
}
|
109
|
+
},
|
110
|
+
{
|
111
|
+
pattern: /ss/,
|
112
|
+
regexp: "\\d\\d",
|
113
|
+
fn: function(date, value) {
|
114
|
+
date.setSeconds(value);
|
115
|
+
}
|
116
|
+
},
|
117
|
+
{
|
118
|
+
pattern: /SSS/,
|
119
|
+
regexp: "\\d\\d\\d",
|
120
|
+
fn: function(date, value) {
|
121
|
+
date.setMilliseconds(value);
|
122
|
+
}
|
123
|
+
},
|
124
|
+
{
|
125
|
+
pattern: /O/,
|
126
|
+
regexp: "[+-]\\d{3,4}|Z",
|
127
|
+
fn: function(date, value) {
|
128
|
+
if (value === "Z") {
|
129
|
+
value = 0;
|
130
|
+
}
|
131
|
+
var offset = Math.abs(value);
|
132
|
+
var minutes = (offset % 100) + Math.floor(offset / 100) * 60;
|
133
|
+
date.setMinutes(date.getMinutes() + (value > 0 ? minutes : -minutes));
|
134
|
+
}
|
135
|
+
}
|
87
136
|
];
|
88
137
|
|
89
|
-
var parsedPattern = matchers.reduce(
|
90
|
-
|
91
|
-
m.
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
138
|
+
var parsedPattern = matchers.reduce(
|
139
|
+
function(p, m) {
|
140
|
+
if (m.pattern.test(p.regexp)) {
|
141
|
+
m.index = p.regexp.match(m.pattern).index;
|
142
|
+
p.regexp = p.regexp.replace(m.pattern, "(" + m.regexp + ")");
|
143
|
+
} else {
|
144
|
+
m.index = -1;
|
145
|
+
}
|
146
|
+
return p;
|
147
|
+
},
|
148
|
+
{ regexp: pattern, index: [] }
|
149
|
+
);
|
98
150
|
|
99
151
|
var dateFns = matchers.filter(function(m) {
|
100
152
|
return m.index > -1;
|
101
153
|
});
|
102
|
-
dateFns.sort(function(a, b) {
|
154
|
+
dateFns.sort(function(a, b) {
|
155
|
+
return a.index - b.index;
|
156
|
+
});
|
103
157
|
|
104
158
|
var matcher = new RegExp(parsedPattern.regexp);
|
105
159
|
var matches = matcher.exec(str);
|
106
160
|
if (matches) {
|
107
|
-
var date = module.exports.now();
|
161
|
+
var date = missingValuesDate || module.exports.now();
|
108
162
|
dateFns.forEach(function(f, i) {
|
109
|
-
f.fn(date, matches[i+1]);
|
163
|
+
f.fn(date, matches[i + 1]);
|
110
164
|
});
|
111
165
|
return date;
|
112
166
|
}
|
113
167
|
|
114
|
-
throw new Error(
|
168
|
+
throw new Error(
|
169
|
+
"String '" + str + "' could not be parsed as '" + pattern + "'"
|
170
|
+
);
|
115
171
|
}
|
116
172
|
|
117
|
-
function parse(pattern, str) {
|
173
|
+
function parse(pattern, str, missingValuesDate) {
|
118
174
|
if (!pattern) {
|
119
|
-
throw new Error(
|
175
|
+
throw new Error("pattern must be supplied");
|
120
176
|
}
|
121
177
|
|
122
|
-
return extractDateParts(pattern, str);
|
178
|
+
return extractDateParts(pattern, str, missingValuesDate);
|
123
179
|
}
|
124
180
|
|
125
181
|
/**
|
@@ -133,7 +189,7 @@ module.exports = asString;
|
|
133
189
|
module.exports.asString = asString;
|
134
190
|
module.exports.parse = parse;
|
135
191
|
module.exports.now = now;
|
136
|
-
module.exports.ISO8601_FORMAT =
|
137
|
-
module.exports.ISO8601_WITH_TZ_OFFSET_FORMAT =
|
138
|
-
module.exports.DATETIME_FORMAT =
|
139
|
-
module.exports.ABSOLUTETIME_FORMAT =
|
192
|
+
module.exports.ISO8601_FORMAT = "yyyy-MM-ddThh:mm:ss.SSS";
|
193
|
+
module.exports.ISO8601_WITH_TZ_OFFSET_FORMAT = "yyyy-MM-ddThh:mm:ss.SSSO";
|
194
|
+
module.exports.DATETIME_FORMAT = "dd MM yyyy hh:mm:ss.SSS";
|
195
|
+
module.exports.ABSOLUTETIME_FORMAT = "hh:mm:ss.SSS";
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "date-format",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.1.0",
|
4
4
|
"description": "Formatting Date objects as strings since 2013",
|
5
5
|
"main": "lib/index.js",
|
6
6
|
"repository": {
|
@@ -25,8 +25,8 @@
|
|
25
25
|
"readmeFilename": "README.md",
|
26
26
|
"gitHead": "bf59015ab6c9e86454b179374f29debbdb403522",
|
27
27
|
"devDependencies": {
|
28
|
-
"eslint": "^5.
|
29
|
-
"eslint-plugin-mocha": "^5.
|
28
|
+
"eslint": "^5.16.0",
|
29
|
+
"eslint-plugin-mocha": "^5.3.0",
|
30
30
|
"mocha": "^5.2.0",
|
31
31
|
"should": "^13.2.3"
|
32
32
|
}
|
package/test/parse-test.js
CHANGED
@@ -1,31 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require(
|
4
|
-
var dateFormat = require(
|
5
|
-
|
6
|
-
describe(
|
7
|
-
it(
|
8
|
-
(function() {
|
9
|
-
|
10
|
-
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
require("should");
|
4
|
+
var dateFormat = require("../lib");
|
5
|
+
|
6
|
+
describe("dateFormat.parse", function() {
|
7
|
+
it("should require a pattern", function() {
|
8
|
+
(function() {
|
9
|
+
dateFormat.parse();
|
10
|
+
}.should.throw(/pattern must be supplied/));
|
11
|
+
(function() {
|
12
|
+
dateFormat.parse(null);
|
13
|
+
}.should.throw(/pattern must be supplied/));
|
14
|
+
(function() {
|
15
|
+
dateFormat.parse("");
|
16
|
+
}.should.throw(/pattern must be supplied/));
|
11
17
|
});
|
12
18
|
|
13
|
-
describe(
|
14
|
-
it(
|
15
|
-
dateFormat.parse(
|
19
|
+
describe("with a pattern that has no replacements", function() {
|
20
|
+
it("should return a new date when the string matches", function() {
|
21
|
+
dateFormat.parse("cheese", "cheese").should.be.a.Date();
|
16
22
|
});
|
17
23
|
|
18
|
-
it(
|
24
|
+
it("should throw if the string does not match", function() {
|
19
25
|
(function() {
|
20
|
-
dateFormat.parse(
|
21
|
-
}
|
26
|
+
dateFormat.parse("cheese", "biscuits");
|
27
|
+
}.should.throw(/String 'biscuits' could not be parsed as 'cheese'/));
|
22
28
|
});
|
23
29
|
});
|
24
30
|
|
25
|
-
describe(
|
26
|
-
var pattern =
|
31
|
+
describe("with a full pattern", function() {
|
32
|
+
var pattern = "yyyy-MM-dd hh:mm:ss.SSSO";
|
27
33
|
|
28
|
-
it(
|
34
|
+
it("should return the correct date if the string matches", function() {
|
29
35
|
var testDate = new Date();
|
30
36
|
testDate.setFullYear(2018);
|
31
37
|
testDate.setMonth(8);
|
@@ -34,21 +40,30 @@ describe('dateFormat.parse', function() {
|
|
34
40
|
testDate.setMinutes(10);
|
35
41
|
testDate.setSeconds(12);
|
36
42
|
testDate.setMilliseconds(392);
|
37
|
-
testDate.getTimezoneOffset = function() {
|
38
|
-
|
39
|
-
|
43
|
+
testDate.getTimezoneOffset = function() {
|
44
|
+
return 600;
|
45
|
+
};
|
46
|
+
|
47
|
+
dateFormat
|
48
|
+
.parse(pattern, "2018-09-13 08:10:12.392+1000")
|
49
|
+
.getTime()
|
50
|
+
.should.eql(testDate.getTime());
|
40
51
|
});
|
41
52
|
|
42
|
-
it(
|
53
|
+
it("should throw if the string does not match", function() {
|
43
54
|
(function() {
|
44
|
-
dateFormat.parse(pattern,
|
45
|
-
}
|
55
|
+
dateFormat.parse(pattern, "biscuits");
|
56
|
+
}.should.throw(
|
57
|
+
/String 'biscuits' could not be parsed as 'yyyy-MM-dd hh:mm:ss.SSSO'/
|
58
|
+
));
|
46
59
|
});
|
47
60
|
});
|
48
61
|
|
49
|
-
describe(
|
62
|
+
describe("with a partial pattern", function() {
|
50
63
|
var testDate = new Date();
|
51
|
-
dateFormat.now = function() {
|
64
|
+
dateFormat.now = function() {
|
65
|
+
return testDate;
|
66
|
+
};
|
52
67
|
|
53
68
|
function verifyDate(actual, expected) {
|
54
69
|
actual.getFullYear().should.eql(expected.year || testDate.getFullYear());
|
@@ -57,53 +72,69 @@ describe('dateFormat.parse', function() {
|
|
57
72
|
actual.getHours().should.eql(expected.hours || testDate.getHours());
|
58
73
|
actual.getMinutes().should.eql(expected.minutes || testDate.getMinutes());
|
59
74
|
actual.getSeconds().should.eql(expected.seconds || testDate.getSeconds());
|
60
|
-
actual
|
75
|
+
actual
|
76
|
+
.getMilliseconds()
|
77
|
+
.should.eql(expected.milliseconds || testDate.getMilliseconds());
|
61
78
|
}
|
62
79
|
|
63
|
-
it(
|
64
|
-
var date = dateFormat.parse(
|
80
|
+
it("should return a date with missing values defaulting to current time", function() {
|
81
|
+
var date = dateFormat.parse("yyyy-MM", "2015-09");
|
65
82
|
verifyDate(date, { year: 2015, month: 8 });
|
66
83
|
});
|
67
84
|
|
68
|
-
it(
|
69
|
-
var
|
85
|
+
it("should use a passed in date for missing values", function() {
|
86
|
+
var missingValueDate = new Date(2010, 1, 11, 10, 30, 12, 100);
|
87
|
+
var date = dateFormat.parse("yyyy-MM", "2015-09", missingValueDate);
|
88
|
+
verifyDate(date, {
|
89
|
+
year: 2015,
|
90
|
+
month: 8,
|
91
|
+
day: 11,
|
92
|
+
hours: 10,
|
93
|
+
minutes: 30,
|
94
|
+
seconds: 12,
|
95
|
+
milliseconds: 100
|
96
|
+
});
|
97
|
+
});
|
98
|
+
|
99
|
+
it("should handle variations on the same pattern", function() {
|
100
|
+
var date = dateFormat.parse("MM-yyyy", "09-2015");
|
70
101
|
verifyDate(date, { year: 2015, month: 8 });
|
71
102
|
|
72
|
-
date = dateFormat.parse(
|
103
|
+
date = dateFormat.parse("yyyy MM", "2015 09");
|
73
104
|
verifyDate(date, { year: 2015, month: 8 });
|
74
105
|
|
75
|
-
date = dateFormat.parse(
|
106
|
+
date = dateFormat.parse("MM, yyyy.", "09, 2015.");
|
76
107
|
verifyDate(date, { year: 2015, month: 8 });
|
77
108
|
});
|
78
109
|
|
79
|
-
it(
|
80
|
-
var date = dateFormat.parse(
|
110
|
+
it("should match all the date parts", function() {
|
111
|
+
var date = dateFormat.parse("dd", "21");
|
81
112
|
verifyDate(date, { day: 21 });
|
82
113
|
|
83
|
-
date = dateFormat.parse(
|
114
|
+
date = dateFormat.parse("hh", "12");
|
84
115
|
verifyDate(date, { hours: 12 });
|
85
116
|
|
86
|
-
date = dateFormat.parse(
|
87
|
-
verifyDate(date,
|
117
|
+
date = dateFormat.parse("mm", "34");
|
118
|
+
verifyDate(date, { minutes: 34 });
|
88
119
|
|
89
|
-
date = dateFormat.parse(
|
120
|
+
date = dateFormat.parse("ss", "59");
|
90
121
|
verifyDate(date, { seconds: 59 });
|
91
122
|
|
92
|
-
date = dateFormat.parse(
|
123
|
+
date = dateFormat.parse("ss.SSS", "23.452");
|
93
124
|
verifyDate(date, { seconds: 23, milliseconds: 452 });
|
94
125
|
|
95
|
-
date = dateFormat.parse(
|
126
|
+
date = dateFormat.parse("hh:mm O", "05:23 +1000");
|
96
127
|
verifyDate(date, { hours: 15, minutes: 23 });
|
97
128
|
|
98
|
-
date = dateFormat.parse(
|
129
|
+
date = dateFormat.parse("hh:mm O", "05:23 -200");
|
99
130
|
verifyDate(date, { hours: 3, minutes: 23 });
|
100
131
|
|
101
|
-
date = dateFormat.parse(
|
132
|
+
date = dateFormat.parse("hh:mm O", "05:23 +0930");
|
102
133
|
verifyDate(date, { hours: 14, minutes: 53 });
|
103
134
|
});
|
104
135
|
});
|
105
136
|
|
106
|
-
describe(
|
137
|
+
describe("with a date formatted by this library", function() {
|
107
138
|
var testDate = new Date();
|
108
139
|
testDate.setUTCFullYear(2018);
|
109
140
|
testDate.setUTCMonth(8);
|
@@ -113,27 +144,34 @@ describe('dateFormat.parse', function() {
|
|
113
144
|
testDate.setUTCSeconds(12);
|
114
145
|
testDate.setUTCMilliseconds(392);
|
115
146
|
|
116
|
-
it(
|
117
|
-
dateFormat
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
147
|
+
it("should format and then parse back to the same date", function() {
|
148
|
+
dateFormat
|
149
|
+
.parse(
|
150
|
+
dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT,
|
151
|
+
dateFormat(dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT, testDate)
|
152
|
+
)
|
153
|
+
.should.eql(testDate);
|
154
|
+
|
155
|
+
dateFormat
|
156
|
+
.parse(
|
157
|
+
dateFormat.ISO8601_FORMAT,
|
158
|
+
dateFormat(dateFormat.ISO8601_FORMAT, testDate)
|
159
|
+
)
|
160
|
+
.should.eql(testDate);
|
161
|
+
|
162
|
+
dateFormat
|
163
|
+
.parse(
|
164
|
+
dateFormat.DATETIME_FORMAT,
|
165
|
+
dateFormat(dateFormat.DATETIME_FORMAT, testDate)
|
166
|
+
)
|
167
|
+
.should.eql(testDate);
|
168
|
+
|
169
|
+
dateFormat
|
170
|
+
.parse(
|
171
|
+
dateFormat.ABSOLUTETIME_FORMAT,
|
172
|
+
dateFormat(dateFormat.ABSOLUTETIME_FORMAT, testDate)
|
173
|
+
)
|
174
|
+
.should.eql(testDate);
|
136
175
|
});
|
137
|
-
|
138
176
|
});
|
139
177
|
});
|