true-time-format
Advanced tools
Comparing version 1.0.1 to 1.0.2
67
index.js
@@ -11,2 +11,3 @@ let | ||
EXPIRESDAY = 20181228, | ||
EXPIRED = `Leapseconds list has expired on ${EXPIRESDAY}, ${ISSUES}`, | ||
LEEPSECOND = [ | ||
@@ -97,8 +98,13 @@ 19720630, | ||
function offset(s) { | ||
let x = parseInt(s), y = x % 100; | ||
if (x < -1200 || x > 1200 || y < -59 || y > 59) | ||
throw Error('invalid Time offset from UTC: ' + s); | ||
let x = parseInt(s); | ||
if (invalidOffset(x)) | ||
throw Error('Invalid Time offset from UTC: ' + s); | ||
return x; | ||
} | ||
function invalidOffset(x) { | ||
let y = x % 100; | ||
return x < -1200 || x > 1200 || y < -59 || y > 59; | ||
} | ||
class Time { | ||
@@ -159,4 +165,3 @@ constructor() { | ||
let x = t.year * 10000 + t.month * 100 + t.day; | ||
if (x > EXPIRESDAY) | ||
throw new Error(`Leapseconds list has expired on ${EXPIRESDAY}, ${ISSUES}`); | ||
if (x > EXPIRESDAY) throw new Error(EXPIRED); | ||
@@ -221,6 +226,15 @@ if (t.hour != 23 || t.minute != 59 || t.day > 31 || LEEPSECOND.indexOf(x) < 0) | ||
m = timeString | ||
.match(/(GMT|UTC|Z)([+-]?)(\d{0,2}):?(\d{0,2})/); | ||
.match(/(GMT|UTC|Z)([+-]?)(\d{0,2})(:?)(\d{0,2})/); | ||
i = m && 1 || 0; | ||
if (!i) { | ||
m = timeString.match(/([+-])(\d{1,2})(:?)(\d{0,2})$/); | ||
// Exclude: Feb-2018, Feb-28-2018, 28-Feb-2018, 28-02-2018, -69 | ||
if (m && m[1] === '-' && !m[3]) { | ||
let x = timeString.substring(0, m.index).match(/(\d+|[A-Za-z]+)$/); | ||
if (!m.index || x && (x.index === 0 || timeString[x.index - 1] === '-')) | ||
m = null; | ||
} | ||
} | ||
if (!i) m = timeString.match(/([+-])(\d{1,2}):?(\d{0,2})$/); | ||
if (m && m[0].endsWith(':')) return ''; | ||
@@ -230,4 +244,5 @@ if (!m) | ||
else { | ||
t.offset = 100 * parseInt(m[i + 2] || '0') + parseInt(m[i + 3] || '0'); | ||
t.offset = 100 * parseInt(m[i + 2] || '0') + parseInt(m[i + 4] || '0'); | ||
if (m[i + 1] === '-') t.offset = -t.offset; | ||
if(invalidOffset(t.offset)) return ''; | ||
timeString = trim(timeString, m.index, m[0].length); | ||
@@ -259,13 +274,15 @@ } | ||
t = new Time(), | ||
seq = this.normalize(timeString, t) | ||
.split(/(\d+|[A-Za-z]+)/) | ||
.filter(function(s, i) { | ||
return i & 1; | ||
}), | ||
layout = this.layout, | ||
normal = this.normalize(timeString, t), | ||
bc = normal.startsWith('-') || normal.startsWith('BC'), | ||
seq = normal.split(/[^\dA-Za-z]+/), | ||
form; | ||
layout = this.layout, | ||
form = seq.reduce(function(sum, s) { | ||
return sum + (s[0] > '9' ? 'M' : s.length <= 2 && 2 || | ||
s.length <= 14 && s.length || '?'); | ||
}, ''); | ||
if (bc) seq.shift(); | ||
form = seq.reduce(function(sum, s) { | ||
return sum + (s[0] > '9' ? 'M' : s.length <= 2 && 2 || | ||
s.length <= 14 && s.length || '?'); | ||
}, ''); | ||
if (!form || form.length > 6) return null; | ||
@@ -276,2 +293,4 @@ | ||
if (bc && layout && layout[0] !== 'Y') return null; | ||
if (layout && layout.length !== form.length && form.length > 2) { | ||
@@ -284,3 +303,3 @@ let | ||
.concat(seq.slice(0, i)).concat(seq.slice(i + 1)); | ||
layout = layout.slice(i,i+3) + layout.slice(0, i) + layout.slice(i + 3); | ||
layout = layout.slice(i, i + 3) + layout.slice(0, i) + layout.slice(i + 3); | ||
form = layout; | ||
@@ -295,6 +314,6 @@ } | ||
if(i===-1) return null; | ||
if (i === -1) return null; | ||
if(i) | ||
layout = layout.slice(i,i+3) + | ||
if (i) | ||
layout = layout.slice(i, i + 3) + | ||
layout.slice(0, i) + layout.slice(i + 3); | ||
@@ -323,6 +342,8 @@ | ||
let since = this.since; | ||
let since = bc ? 0 : this.since; | ||
for (let i = 0; i < seq.length; i++) | ||
if (!assign(layout[i], seq[i], t, since)) | ||
return null; | ||
if (bc) t.year = -t.year; | ||
return assert(t); | ||
@@ -329,0 +350,0 @@ } |
{ | ||
"name": "true-time-format", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "True class to parse, format, and manipulate datetimes.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -39,2 +39,3 @@ let | ||
'030406.999 20160102 ', | ||
'Jan-02-2016 03:04:06.999', | ||
'Jan 02 2016 03:04:06.999', | ||
@@ -86,1 +87,75 @@ 'Jan 2 2016 03:04:06.999', | ||
}); | ||
test('UTC offsets', function(t) { | ||
let ymd = '2018-02-28'; | ||
[ | ||
'2018-02-28','Z', | ||
'Feb-28-2018','Z', | ||
'2018-02-28Z+0800', '+', | ||
'2018-02-28 Z+8:0', '+', | ||
'2018-02-28 Z+8', '+', | ||
'2018-02-28Z-0800', '-', | ||
'2018-02-28 Z-8:0', '-', | ||
'2018-02-28 Z-8', '-', | ||
'2018-02-28Z+0800 LSC', '+', | ||
'2018-02-28 Z+8:0 LSC', '+', | ||
'2018-02-28 Z+8 LSC', '+', | ||
'2018-02-28Z-0800 LSC', '-', | ||
'2018-02-28 Z-8:0 LSC', '-', | ||
'2018-02-28 Z-8 LSC', '-', | ||
].forEach((s,i,a) => { | ||
if (i & 1) return; | ||
let date = String(time.parse(s)), | ||
offset = date.endsWith('Z') && 'Z' || date.slice(-5); | ||
t.equal(date.slice(0, 10), ymd, s); | ||
t.equal(offset, a[i + 1] === 'Z' && 'Z' || a[i + 1] + '0800', s); | ||
}); | ||
t.equal(String(time.parse('02-2018')).slice(0, 7), '2018-02', '02-2018'); | ||
t.equal(String(time.parse('-2018')).slice(0, 8), '-2018-00', '-2018'); | ||
t.end(); | ||
}); | ||
test('null', function(t) { | ||
let ymd = new time.Parser('YMD'); | ||
[ | ||
'2018022803', | ||
'20180229', | ||
'20180100', | ||
'20180132', | ||
'20181100', | ||
'20181131', | ||
'20181301', | ||
'20180001', | ||
'2018MM01' | ||
].forEach((s,i,a) => { | ||
t.equal(String(time.parse(s)), 'null', s); | ||
t.equal(String(ymd.parse(s)), 'null', s); | ||
}); | ||
t.end(); | ||
}); | ||
test('throw Error', function(t) { | ||
t.throws(()=> { | ||
new time.Parser('YMDY'); | ||
}); | ||
t.throws(()=> { | ||
[ | ||
'2018Z-13', | ||
'2018Z+13', | ||
'2018Z-1160', | ||
'2018Z+1160', | ||
'19710630235960', | ||
'19711231235960', | ||
'19720630010160', | ||
'99991231235960', | ||
].forEach(time.parse); | ||
}, /^Error: (Dup|Inv|Leap)/); | ||
t.end(); | ||
}); |
16705
474