chronoshift
Version:
A tiny library for shifting time with timezones
184 lines (183 loc) • 6.29 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseSQLDate = parseSQLDate;
exports.parseISODate = parseISODate;
exports.parseInterval = parseInterval;
const date_1 = require("@internationalized/date");
const duration_1 = require("../duration/duration");
const timezone_1 = require("../timezone/timezone");
function parseYear(v) {
if (v.length === 2) {
const vn = parseInt(v, 10);
return (vn < 70 ? 2000 : 1900) + vn;
}
else if (v.length === 4) {
return parseInt(v, 10);
}
else {
throw new Error('Invalid year in date');
}
}
function parseMonth(v) {
const vn = parseInt(v, 10);
if (vn <= 0 || 12 < vn)
throw new Error('Invalid month in date');
return vn - 1;
}
function parseDay(v) {
const vn = parseInt(v, 10);
if (vn <= 0 || 31 < vn)
throw new Error('Invalid day in date');
return vn;
}
function parseHour(v) {
const vn = parseInt(v, 10);
if (vn < 0 || 24 < vn)
throw new Error('Invalid hour in date');
return vn;
}
function parseMinute(v) {
const vn = parseInt(v, 10);
if (vn < 0 || 60 < vn)
throw new Error('Invalid minute in date');
return vn;
}
function parseSecond(v) {
const vn = parseInt(v, 10);
if (vn < 0 || 60 < vn)
throw new Error('Invalid second in date');
return vn;
}
function parseMillisecond(v) {
if (!v)
return 0;
return parseInt(v.substr(0, 3), 10);
}
function parseSQLDate(type, v) {
if (type === 't')
throw new Error('time literals are not supported');
let m;
let d;
if (type === 'ts') {
if ((m = /^(\d{2}(?:\d{2})?)(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/.exec(v))) {
d = Date.UTC(parseYear(m[1]), parseMonth(m[2]), parseDay(m[3]), parseHour(m[4]), parseMinute(m[5]), parseSecond(m[6]));
}
else if ((m =
/^(\d{2}(?:\d{2})?)[~!@#$%^&*()_+=:.\-\/](\d{1,2})[~!@#$%^&*()_+=:.\-\/](\d{1,2})[T ](\d{1,2})[~!@#$%^&*()_+=:.\-\/](\d{1,2})[~!@#$%^&*()_+=:.\-\/](\d{1,2})(?:\.(\d{1,6}))?$/.exec(v))) {
d = Date.UTC(parseYear(m[1]), parseMonth(m[2]), parseDay(m[3]), parseHour(m[4]), parseMinute(m[5]), parseSecond(m[6]), parseMillisecond(m[7]));
}
else {
throw new Error('Invalid timestamp');
}
}
else {
if ((m = /^(\d{2}(?:\d{2})?)(\d{2})(\d{2})$/.exec(v))) {
d = Date.UTC(parseYear(m[1]), parseMonth(m[2]), parseDay(m[3]));
}
else if ((m = /^(\d{2}(?:\d{2})?)[~!@#$%^&*()_+=:.\-\/](\d{1,2})[~!@#$%^&*()_+=:.\-\/](\d{1,2})$/.exec(v))) {
d = Date.UTC(parseYear(m[1]), parseMonth(m[2]), parseDay(m[3]));
}
else {
throw new Error('Invalid date');
}
}
return new Date(d);
}
const numericKeys = [1, 4, 5, 6, 10, 11];
function parseISODate(date, timezone = timezone_1.Timezone.UTC) {
let struct;
let minutesOffset = 0;
if ((struct =
/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2})(?::?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?)?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?$/.exec(date))) {
for (let i = 0, k; (k = numericKeys[i]); ++i) {
struct[k] = +struct[k] || 0;
}
struct[2] = (+struct[2] || 1) - 1;
struct[3] = +struct[3] || 1;
struct[7] = struct[7] ? +(struct[7] + '00').slice(0, 3) : 0;
if ((struct[8] === undefined || struct[8] === '') &&
(struct[9] === undefined || struct[9] === '') &&
!timezone_1.Timezone.UTC.equals(timezone || undefined)) {
if (timezone === null) {
return new Date(struct[1], struct[2], struct[3], struct[4], struct[5], struct[6], struct[7]);
}
else {
const dt = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5], struct[6], struct[7]);
const tzd = (0, date_1.fromDate)(new Date(dt), timezone.toString());
return new Date(dt - tzd.offset);
}
}
else {
if (struct[8] !== 'Z' && struct[9] !== undefined) {
minutesOffset = struct[10] * 60 + struct[11];
if (struct[9] === '+') {
minutesOffset = 0 - minutesOffset;
}
}
return new Date(Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]));
}
}
else {
return;
}
}
function parseInterval(str, timezone = timezone_1.Timezone.UTC, now = new Date()) {
const parts = str.split('/');
if (parts.length > 2)
throw new Error(`Can not parse string ${str}`);
let start;
let end;
let duration;
const p0 = parts[0];
if (parts.length === 1) {
duration = duration_1.Duration.fromJS(p0);
}
else {
const p1 = parts[1];
if (p0[0] === 'P') {
duration = duration_1.Duration.fromJS(p0);
end = parseISODate(p1, timezone);
if (!end)
throw new Error(`can not parse '${p1}' as ISO date`);
}
else if (p1[0] === 'P') {
start = parseISODate(p0, timezone);
if (!start)
throw new Error(`can not parse '${p0}' as ISO date`);
duration = duration_1.Duration.fromJS(p1);
}
else {
start = parseISODate(p0, timezone);
if (!start)
throw new Error(`can not parse '${p0}' as ISO date`);
end = parseISODate(p1, timezone);
if (!end)
throw new Error(`can not parse '${p1}' as ISO date`);
if (end < start) {
throw new Error(`start must be <= end in '${str}'`);
}
}
}
let computedStart;
let computedEnd;
if (start) {
computedStart = start;
if (duration) {
computedEnd = duration.shift(computedStart, timezone, 1);
}
else {
computedEnd = end;
}
}
else {
computedEnd = end || now;
computedStart = duration.shift(computedEnd, timezone, -1);
}
return {
computedStart,
computedEnd,
start,
end,
duration,
};
}
;