Initial project upload

This commit is contained in:
Mohamed Mathar Irfan
2026-07-28 17:57:02 +05:30
commit ed6610d5d8
23919 changed files with 3003316 additions and 0 deletions

13
frontend/node_modules/spacetime/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2025 Spencer Kelly
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

620
frontend/node_modules/spacetime/README.md generated vendored Normal file
View File

@@ -0,0 +1,620 @@
<div align="center">
<div>
<img width="277" alt="spacetime logo" src="https://user-images.githubusercontent.com/399657/31140478-80a4269a-a842-11e7-8dbf-b541fe3e87a7.png">
</div>
<a href="https://npmjs.org/package/spacetime">
<img src="https://img.shields.io/npm/v/spacetime.svg?style=flat-square" />
</a>
<a href="https://bundlephobia.com/result?p=spacetime@latest">
<img src="https://badgen.net/bundlephobia/min/spacetime" />
</a>
</div>
<!-- spacer -->
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
Isn't it weird how we can do <i>math</i> in our head, but not <b><i>date math</i></b>?
<div align="left">
<div >
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/><i>- how many days until the end of the year?</i>
</div>
<div >
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/><i>-what time was it, 11 hours ago?</i>
</div>
<div >
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/><i>-is it lunchtime in france?</i>
</div>
</div>
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
and worse - there is no real **_date calculator_**.
<div align="center">
<sub>people end up asking google, and going to weird websites.</sub>
</div>
<img height="10px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="center"><sub>that's bad.</sub></div>
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<b>spacetime</b> is a date-calculator,
<div >
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/><sub>It's very small, and very handy.</sub>
</div>
```js
let s = spacetime.now()
s.diff(s.endOf('year'), 'days')
// 292
s.subtract(11, 'hours').time()
// 6:50am
s = s.goto('Europe/Paris')
s.isAfter(s.time('11:00am'))
// true 🥐
```
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221814-05ed1680-ffb8-11e9-8b6b-c7528d163871.png"/>
</div>
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
- calculate time in remote timezones
- support **daylight savings**, **leap years**, and **hemispheres**
- [Moment-like API](https://beta.observablehq.com/@spencermountain/spacetime-api) _(but immutable)_
- Orient time by quarter, season, month, week..
- _Zero Dependencies_ - (no _[Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)_)
- weighs about 40kb.
- has a cool _[plugin thing](https://observablehq.com/@spencermountain/spacetime)_.
- frequent updates for approaching DST changes
- support for upcoming [Temporal](https://tc39.es/proposal-temporal/docs/) standards
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
```html
<script src="https://unpkg.com/spacetime"></script>
<script>
var d = spacetime('March 1 2012', 'America/New_York')
//set the time
d = d.time('4:20pm')
d = d.goto('America/Los_Angeles')
d.time()
//'1:20pm'
</script>
```
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
`npm install spacetime`
```js
const spacetime = require('spacetime')
let d = spacetime.now('Europe/Paris')
d.dayName()
//'Wednesday'
d.isAsleep()
//true
```
<sub><i>typescript / babel / deno:</i></sub>
```ts
import spacetime from 'spacetime'
let d = spacetime.now()
d.format('nice')
//'Apr 1st, 4:32pm'
```
<div align="right">
<a href="https://github.com/spencermountain/spacetime/wiki/Typescript">ts docs</a>
</div>
<sub><a href="./AGENTS.md"><code>AGENTS.md</code> LLM docs</a></sub>
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="center">
<h3>
<a href="https://beta.observablehq.com/@spencermountain/spacetime">
Demo
</a>
&nbsp; &nbsp;&nbsp; &nbsp;
<a href="https://beta.observablehq.com/@spencermountain/spacetime-api">
Full API
</a>
</h3>
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div>
<img width="550" src="https://user-images.githubusercontent.com/399657/50862221-1d904a00-1369-11e9-891c-5f4e9fbb9ec0.gif" />
</div>
<img height="40px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
plugins:
<div align="center">
<a href="https://github.com/spencermountain/spacetime/tree/master/plugins/geo">spacetime-geo</a>
<a href="https://github.com/spencermountain/spacetime/tree/master/plugins/daylight">spacetime-daylight</a>
<a href="https://github.com/spencermountain/spacetime/tree/master/plugins/age">spacetime-age</a>
</div>
<div align="center">
<a href="https://github.com/spencermountain/scal">spacetime-calendar</a>
<a href="https://github.com/spencermountain/spacetime/tree/master/plugins/week-of-month">week-of-month</a>
<a href="https://github.com/spencermountain/spacetime/tree/master/plugins/week-start">week-start</a>
</div>
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### Date Inputs:
we can parse _[all the normal stuff](https://github.com/spencermountain/spacetime/wiki/Input)_, and some fancy stuff:
```js
//epoch
s = spacetime(1489520157124)
//array [yyyy, m, d] (zero-based months, 1-based days)
s = spacetime([2017, 5, 2])
//iso
s = spacetime('July 2, 2017 5:01:00')
// All inputs accept a timezone, as 2nd param:
s = spacetime(1489520157124, 'Canada/Pacific')
s = spacetime('2019/05/15', 'Canada/Pacific')
// or set the offset right in the date-string (ISO-8601)
s = spacetime('2017-04-03T08:00:00-0700')
// 'Etc/GMT-7'
// Some helpers
s = spacetime.now()
s = spacetime.today() // This morning
s = spacetime.tomorrow() // Tomorrow morning
s = spacetime.min() // the earliest-possible date (271,821 bc)
s = spacetime.max() // the furthest-possible future date (27k years from now)
// To get the native Date object back
// (this bails back to the local timezone)
jsDate = spacetimeDate.toNativeDate()
```
for fancier natural-language inputs, use [compromise-dates](https://github.com/spencermountain/compromise/tree/master/plugins/dates).
<img height="20px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### Get & Set dates:
you can whip things around, but stay intuitive
```js
s.date() // 14
s.year() // 2017
s.season() // Spring
s = s.hour(5) // Change to 5am
s = s.date(15) // Change to the 15th
s = s.day('monday') // Change to (this week's) monday
s = s.day('monday', true) // go forward to monday
s = s.day('monday', false) // go backward to monday
s = s.month('march') // Change to (this year's) March 1st
s = s.quarter(2) // Change to April 1st
s.era() // 'BC'/'AD'
s.decade() // 2000
s.century() // 21
// Percentage-based information
s.progress().month // 0.23 - we're a quarter way through the month
s.progress().day // 0.48 - almost noon
s.progress().hour // 0.99 - 59 minutes and 59 seconds
// Add/subtract methods
s = s.add(1, 'week')
s = s.add(3, 'quarters')
s = s.subtract(2, 'months').add(1, 'day')
// start-of/end-of
s = s.startOf('day') // 12:00am
s = s.startOf('month') // 12:00am, April 1st
s = s.endOf('quarter') // 11:59:59pm, June 30th
s = s.nearest('hour') //round up/down to the hour
s = s.nearest('quarter-hour') //5:15, 5:30, 5:45..
s = s.next('month') //start of the next month
s = s.last('year') //start of the last year
// fill-in all dates between a range
s.every('week', 'Jan 1st 2020') // (in tz of starting-date)
//utilities:
s.clone() // Make a copy
s.isValid() // Sept 32nd → false
s.isAwake() // it's between 8am → 10pm
s.json() // get values in every unit as key-val object
```
if it's **_9am on tuesday_**, and you <i>add a week</i>, it will still be 9am on tuesday.
... even if some crazy changes happen.
setter methods also support a handy 2nd param that controls whether it should be set forward, or backward.
```js
s = s.time('4:00pm') // 4pm today
s = s.time('4:00pm', true) // the next 4pm in the future
s = s.time('4:00pm', false) // the most-recent 4pm
s = s.set('march 5th 2020')
s = s.set('march 4th') // 2020 (same year)
s = s.set('march 4th', true) // 2021
s = s.set('march 6th', false) // 2019
```
it's actually a little surprising how helpful this is.
<img height="20px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### Comparisons:
```js
let s = spacetime([2017, 5, 2])
let start = s.subtract(1, 'milliseconds')
let end = s.add(1, 'milliseconds')
// gt/lt/equals
s.isAfter(d) // True
s.isEqual(d) // False
s.isBefore(d) // False
s.isBetween(start, end, inclusive?) // True
// Comparison by unit
s.isSame(d, 'year') // True
s.isSame(d, 'date') // False
s.diff(d, 'day') // 5
s.diff(d, 'month') // 0
//make a human-readable diff
let before = spacetime([2018, 3, 28])
let now = spacetime([2017, 3, 28]) //one year later
now.since(before)
// {diff: { months: 11, days: 30, ...}, rounded: 'in 12 months' }
```
all comparisons are done with sensitivity of timezone - **_8am EST_** is < **_8am PST_**.
<img height="20px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### Timezones:
the best way to describe a timezone is an [IANA code](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones):
```js
// Roll into a new timezone, at the same moment
s = s.goto('Australia/Brisbane')
```
if you want to support relaxed timezone names like `'EST'`, `Eastern time`, use [timezone-soft](https://github.com/spencermountain/timezone-soft/)
```js
spacetime.extend(require('timezone-soft'))
s = s.goto('milwaukee') // 'America/Chicago'
s = s.goto('-7h') // UTC-7
s = s.goto('GMT+8') // -8h!
// (these should be used with some caution)
```
play-around with timezones, and their DST-changes:
```js
//list timezones by their current time
spacetime.whereIts('8:30pm', '9:30pm') // ['America/Winnipeg', 'America/Yellowknife'... ]
spacetime.whereIts('9am') //(within this hour)
// Timezone metadata
s.timezone().name // 'Canada/Eastern' (either inferred or explicit)
s.hemisphere() // North
s.timezone().current.offset // -4 (in hours)
s.hasDST() // True
s.isDST() // True
//list all timezones
spacetime.timezones()
```
you can flip-around the world pretty quick.
spacetime will use your local timezone, by default:
`.goto(null)` will pluck your current tz safely from your browser or computer.
```js
spacetime().time('4:30pm').goto('Europe/Paris').goto(null).time()
// 4:30pm
```
If, for some reason, you want to change the timezone *without changing the date*, you can do this via the `.timezone(str)` setter:
```js
let s = spacetime('2023-01-01T5:30[America/Denver]')
s = s.timezone('Europe/Zagreb') // hot-swap
console.log(s.isoFull())
// '2023-01-01T05:30:00.000+01:00[Europe/Zagreb]' (same time, new tz)
```
<img height="20px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### Date Formatting:
it's _[a pretty-sensible process](https://github.com/spencermountain/spacetime/wiki/Formatting)_ to create nice-looking dates:
```js
// Date + time formatting
s.format('time') // '5:01am'
s.format('numeric-uk') // 02/03/2017
s.format('month') // 'April'
s.format('month-short') // 'Apr'
s.format('month-pad') // '03'
s.format('iso-month') // '04'
//if you want more complex formats, use {}'s
s.format('{year}-{date-pad}-{month-pad}') // '2018-02-02'
s.format("{hour} o'clock") // '2 o'clock'
s.format('{time}{ampm} sharp') // '2:30pm sharp'
//if you prefer, you can also use unix-formatting
s.unixFmt('yyyy.MM.dd h:mm a') // '2017.Nov.16 11:34 AM'
// support for the new Temporal ISO format
s.format('iso-full') // '2011-12-03T10:15:30.010+01:00[Europe/Paris]'
// support for the SQL ISO 9075 format
s.format('sql') // '2011-12-03 10:15:30'
```
<!-- spacer -->
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="center">
<img src="https://user-images.githubusercontent.com/399657/68221814-05ed1680-ffb8-11e9-8b6b-c7528d163871.png"/>
</div>
## Limitations & caveats
#### ◆ Historical timezone info
DST changes move around all the time, and timezones pop-in and out of existence.
We store and use only the latest DST information, and apply it to historical dates.
#### ◆ International date line
`.goto()` never crosses the date-line. This is mostly the intuitive behaviour.
But if you're in `Fiji` (just west of the date line), and you go to `Midway` (just east of the date line), .goto() will subtract a bunch of hours, instead of just adding one.
#### ◆ Destructive changes
if it's `2:30pm` and you add a month, it should still be `2:30pm`. Some changes are more destructive than others. Many of thse choices are subjective, but also sensible.
#### ◆ 0-based vs 1-based ...
for better or worse we copy the JavaScript spec for 0-based months, and 1-based dates.
ISO-formatting is different, so keep on your toes.
see [more considerations and gotchas](https://github.com/spencermountain/spacetime/wiki)
#### Daylight-savings gotchas
We've written in detail about how spacetime handles Daylight-savings changes [here](https://observablehq.com/@spencermountain/spacetime-daylight-savings-time?collection=@spencermountain/spacetime)
Fall DST changes have an hour that is repeated twice. There are a lot of tricky situations that come from this.
Add 10 minutes at `1:55am`, and a spacetime diff may show `-50mins`. Within an hour of this change, some spacetime methods may be off-by-one hour.
Springtime DST changes are generally smoother than Fall ones.
<!-- spacer -->
<div align="center">
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221632-b9094000-ffb7-11e9-99e0-b48edd6cdf8a.png"/>
</div>
### Config:
#### Ambiguity warnings:
javascript dates use millisecond-epochs, instead of second-epochs, like some other languages.
This is a common bug, and spacetime can warn if you set an epoch within January 1970.
to enable:
```js
let s = spacetime(123456, 'UTC', {
silent: false
})
s.log() // "Jan 1st, 12:02am"
```
There is another situation where you may see a `console.warn` - if you give it a timezone, but then set a ISO-date string with a different offset, like `2017-04-03T08:00:00-0700` (-7hrs UTC offset).
It sets the timezone to UTC-7, but also gives a warning.
```js
let s = spacetime('2017-04-03T08:00:00-0700', 'Canada/Eastern', {
silent: false
})
s.timezone().name // "Etc/GMT-7"
```
#### Configure 'today' context:
spacetime makes some assumptions about some string inputs:
```js
// assumes start of month
let s = spacetime('June 1992')
s.date() // 1
// assumes current year
let s = spacetime('June 5th')
s.year() // 2020 (or whatever it is now)
// assumes Jan 1st
let s = spacetime('2030')
s.month() // 'January'
```
you can configure this assumed date (usually for testing) by passing it in as an option:
```js
let today = {
month: 3,
date: 4,
year: 1996
}
let s = spacetime('June 5th', null, { today: today })
s.year() // 1996
```
it also works for `spacetime.now(tz, {today:today})` and others.
#### Extending/Plugins:
you can throw any methods onto the Spacetime class you want, with `spacetime.extend()`:
```js
spacetime.extend({
isHappyHour: function () {
return this.hour() === 16
}
})
let s = spacetime.now('Australia/Adelaide')
s.isHappyHour()
//false
s = s.time('4:30pm')
s.isHappyHour()
//true
```
#### DD/MM/YYY interpretation:
by default spacetime uses the American interpretation of ambiguous date formats, like javascript does:
```js
spacetime('12/01/2018') //dec 1st
// unless it's clear (>12):
spacetime('13/01/2018') //jan 13th
```
you can change this behaviour by passing in a `dmy` option, like this:
```js
spacetime('12/01/2018', null, { dmy: true }) //jan 12th
```
this format is more common in [britain, and south america](https://en.wikipedia.org/wiki/Date_format_by_country).
#### Custom languages:
```js
let s = spacetime.now()
s.i18n({
days: {
long: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
short: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb']
},
months: {
long: [...],
short: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
},
ampm: {
am: ' a. m.',
pm: ' p. m.'
},
distance: {
past: 'past',
future: 'future',
present: 'present',
now: 'now',
almost: 'almost',
over: 'over',
pastDistance: (value) => `${value} ago`,
futureDistance: (value) => `in ${value}`
},
units: {
second: 'second',
seconds: 'seconds',
minute: 'minute',
minutes: 'minutes',
hour: 'hour',
hours: 'hours',
day: 'day',
days: 'seconds',
month: 'month',
months: 'months',
year: 'year',
years: 'years',
},
useTitleCase: true // automatically in .format()
});
s.format('day') //'Sábado'
```
#### Configure start of week:
by default, the start of the week is monday.
You can determine the week by the official country setting, with [spacetime-week](https://github.com/spencermountain/spacetime-week)
```js
let s = spacetime.now()
s = s.weekStart('sunday')
s = s.startOf('week')
s.dayName()
//sunday
s = s.endOf('week')
s.dayName()
//saturday
```
<!-- spacer -->
<div align="center">
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221824-09809d80-ffb8-11e9-9ef0-6ed3574b0ce8.png"/>
</div>
#### See also:
- [luxon](https://moment.github.io/luxon/) - a small library from the clever moment people
- [date-fns](https://date-fns.org/) - an battle-hardened client-side Date utility
- [sugarjs/dates](https://sugarjs.com/dates/) - well-made date fns + timezone math
- [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat) - some _[sorta-green](https://caniuse.com/#feat=internationalization)_ in-browser date utilities
- [BurntSushi/Jiff](https://github.com/BurntSushi/jiff) - Rust/wasm date library
thank you to the amazing [timeanddate.com](https://www.timeanddate.com/)
Apache 2.0

322
frontend/node_modules/spacetime/api/index.js generated vendored Normal file
View File

@@ -0,0 +1,322 @@
export default {
"main": {
"goto": {
"doc": "move to a new timezone, but at this same moment. Accepts an IANA code or abbreviation",
"out": "clone"
},
"clone": {
"doc": "make a copy of this object, with no references to the original",
"out": "clone"
},
"timezone": {
"doc": "return a bunch of meta-data about your current timezone, or pass a name to swap the timezone while keeping the same date-time",
"out": "Object/clone"
},
"toNativeDate": {
"doc": "return the native javascript Date object at the same epoch (falls back to the local timezone)",
"out": "Date"
},
"format": {
"doc": "output nicely-formatted strings, using a named format or a {token} template",
"out": "String/Object"
},
"unixFmt": {
"doc": "output a formatted string using unix/moment formatting tokens, like 'yyyy.MM.dd h:mm a'",
"out": "String"
},
"startOf": {
"doc": "move to the first millisecond of the day, week, month, year, etc.",
"out": "clone"
},
"endOf": {
"doc": "move to the last millisecond of the day, week, month, year, etc.",
"out": "clone"
},
"add": {
"doc": "increment the time by a number and unit - like an hour, minute, day, or year",
"out": "clone"
},
"subtract": {
"doc": "decrease the time by a number and unit - like an hour, minute, day, or year",
"out": "clone"
},
"next": {
"doc": "go to the beginning of the next unit",
"out": "clone"
},
"last": {
"doc": "go to the beginning of the previous unit",
"out": "clone"
},
"nearest": {
"doc": "move forward/backward to the closest unit",
"out": "clone"
},
"round": {
"doc": "round to either the current, or +1 of this unit (alias of nearest)",
"out": "clone"
},
"every": {
"doc": "list all dates up to a certain time, by a given unit",
"out": "Array"
},
"each": {
"doc": "list all dates between this one and another, by a given unit",
"out": "Array"
},
"isAfter": {
"doc": "pass-in a spacetime object or date input and see if it takes-place after your spacetime date/time",
"out": "Boolean"
},
"isBefore": {
"doc": "pass-in a spacetime object or date input and see if it takes-place before your spacetime date/time",
"out": "Boolean"
},
"isEqual": {
"doc": "is this date on the exact same millisecond as another",
"out": "Boolean"
},
"isBetween": {
"doc": "is this date between these start and end dates? accepts an optional isInclusive flag",
"out": "Boolean"
},
"isSame": {
"doc": "detect if two date/times are the same day, week, or year, etc",
"out": "Boolean"
},
"diff": {
"doc": "given a date and a unit, count how many of them you'd need to make the dates equal. Without a unit, returns a count of every unit.",
"out": "Number/Object"
},
"since": {
"doc": "create a human-readable diff between the two dates, like 'in 5 months'",
"out": "Object"
},
"from": {
"doc": "create a human-readable diff between the two dates (alias of since)",
"out": "Object"
},
"fromNow": {
"doc": "create a human-readable diff between now and the given date",
"out": "Object"
}
},
"getters": {
"millisecond": {
"doc": "set or return the current number of milliseconds (0-999)",
"out": "clone/Number"
},
"second": {
"doc": "set or return the current number of seconds (0-59)",
"out": "clone/Number"
},
"minute": {
"doc": "set or return the current number of minutes (0-59)",
"out": "clone/Number"
},
"hour": {
"doc": "set or return the current hour, in 24 time (0-23). also accepts/parses '3pm'",
"out": "clone/Number"
},
"hour12": {
"doc": "set or return the current hour, in 12-hour format (0-11). also accepts/parses '3pm'",
"out": "clone/Number"
},
"date": {
"doc": "set or return the day-number of the month (1- max31)",
"out": "clone/Number"
},
"month": {
"doc": "set or return the zero-based month-number (0-11). Also accepts 'June', or 'oct'.",
"out": "clone/Number"
},
"year": {
"doc": "set or return the 4-digit year as an integer",
"out": "clone/Number"
},
"decade": {
"doc": "set or return the current decade, like 2020",
"out": "clone/Number"
},
"century": {
"doc": "set or return the current century, like 21",
"out": "clone/Number"
},
"millennium": {
"doc": "set or return the current millennium, like 3",
"out": "clone/Number"
},
"dayOfYear": {
"doc": "set or return the day of the year (1-366). Jan 1st is 1, Dec 31st is 366.",
"out": "clone/Number"
},
"time": {
"doc": "set or return a formatted, 12-hour time, like '11:30pm'",
"out": "clone/String"
},
"week": {
"doc": "set or return the week-number of the year (1-52).",
"out": "clone/Number"
},
"quarter": {
"doc": "set or return the fiscal-quarter (1-4)",
"out": "clone/Number"
},
"season": {
"doc": "set or return the name of the season, spring/summer/fall/autumn/winter",
"out": "clone/String"
},
"era": {
"doc": "set or return the era, 'BC' or 'AD'",
"out": "clone/String"
},
"hourFloat": {
"doc": "set or return the hour + minute in decimal form, so '3:30am' is 3.5",
"out": "clone/Number"
},
"day": {
"doc": "set or return the day of the week as an integer, starting on sunday (day-0). Also accepts names like 'wednesday', or 'thurs'",
"out": "clone/Number"
},
"dayName": {
"doc": "set or return the day of the week as a string, like 'wednesday'",
"out": "clone/String"
},
"ampm": {
"doc": "set or return whether the time is am or pm",
"out": "clone/String"
},
"dayTime": {
"doc": "set or return the general time-of-day, like 'afternoon'",
"out": "clone/String"
},
"monthName": {
"doc": "set or return the current month as a string, like 'april'",
"out": "clone/String"
},
"epochSeconds": {
"doc": "set or return the time in seconds since jan 1 1970",
"out": "clone/Number"
},
"iso": {
"doc": "set or return the traditional ISO 8601 datetime string",
"out": "clone/String"
},
"isoFull": {
"doc": "set or return the extended ISO datetime string (RFC 9557), with offset and [timezone]",
"out": "clone/String"
},
"json": {
"doc": "set or return all date units as a key-value object",
"out": "clone/Object"
}
},
"utils": {
"set": {
"doc": "change to a new date.",
"out": "clone"
},
"isValid": {
"doc": "does this time exist on the gregorian/javascript calendar?",
"out": "Boolean"
},
"log": {
"doc": "pretty-print the date to the console, for nicer debugging",
"out": "clone"
},
"logYear": {
"doc": "pretty-print the full date to the console, for nicer debugging",
"out": "clone"
},
"progress": {
"doc": "Between 0-1, how far the moment lands between the start and end of the day/week/month/year.",
"out": "Object"
},
"leapYear": {
"doc": "is the current year a leap year?",
"out": "Boolean"
},
"isDST": {
"doc": "is daylight-savings-time activated right now, for this timezone?",
"out": "Boolean"
},
"inDST": {
"doc": "is daylight-savings-time activated right now, for this timezone? (alias of isDST)",
"out": "Boolean"
},
"hasDST": {
"doc": "does this timezone ever use daylight-savings",
"out": "Boolean"
},
"offset": {
"doc": "the current, DST-aware time-difference from UTC, in hours",
"out": "Number"
},
"hemisphere": {
"doc": "which hemisphere is this timezone in, 'North' or 'South'",
"out": "String"
},
"isAwake": {
"doc": "checks if the current time is between 8am and 10pm",
"out": "Boolean"
},
"isAsleep": {
"doc": "checks if the current time is between 10pm and 8am",
"out": "Boolean"
},
"i18n": {
"doc": "changes the names of months and days, for non-english formatting",
"out": "clone"
},
"weekStart": {
"doc": "change the day the week starts on (0-6, default is monday)",
"out": "clone"
},
"daysInMonth": {
"doc": "returns the amount of days the current month has (December => 31, June => 30, ...)",
"out": "Number"
}
},
"statics": {
"now": {
"doc": "create a spacetime object at the current moment. Accepts a timezone as the first argument.",
"out": "clone"
},
"today": {
"doc": "create a spacetime object at the start of today (this morning)",
"out": "clone"
},
"tomorrow": {
"doc": "create a spacetime object at the start of tomorrow",
"out": "clone"
},
"yesterday": {
"doc": "create a spacetime object at the start of yesterday",
"out": "clone"
},
"min": {
"doc": "create a spacetime object at the earliest-possible date (271,821 bc)",
"out": "clone"
},
"max": {
"doc": "create a spacetime object at the furthest-possible future date",
"out": "clone"
},
"fromUnixSeconds": {
"doc": "create a spacetime object from an epoch in seconds (instead of milliseconds)",
"out": "clone"
},
"extend": {
"doc": "add custom methods (or a plugin) to the spacetime object",
"out": "spacetime"
},
"timezones": {
"doc": "get a list of all known timezones and their offsets",
"out": "Object"
},
"whereIts": {
"doc": "list the timezones where it's currently a given time, like '8:30pm'",
"out": "Array"
}
}
}

4248
frontend/node_modules/spacetime/builds/spacetime.cjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1
frontend/node_modules/spacetime/builds/spacetime.mjs generated vendored Normal file

File diff suppressed because one or more lines are too long

67
frontend/node_modules/spacetime/package.json generated vendored Normal file
View File

@@ -0,0 +1,67 @@
{
"name": "spacetime",
"version": "7.13.0",
"description": "figure-out dates across timezones",
"main": "src/index.js",
"unpkg": "builds/spacetime.min.js",
"types": "types/index.d.ts",
"type": "module",
"sideEffects": false,
"exports": {
".": {
"import": {
"types": "./types/index.d.ts",
"default": "./builds/spacetime.mjs"
},
"require": {
"types": "./types/index.d.cts",
"default": "./builds/spacetime.cjs"
}
}
},
"scripts": {
"build": "npm run pack && npm run version && rollup -c --silent",
"build:tz": "node ./scripts/updateZonefile.js",
"pack": "node ./zonefile/pack.js",
"version": "node ./scripts/version.js",
"watch": "node --watch ./scratch.js",
"test": "tape ./test/**/*.test.js | tap-dancer --color always",
"testb": "TESTENV=prod tape ./test/**/*.test.js | tap-dancer --color always",
"test:types": "tsx ./test/types/index.ts | tap-dancer --color always",
"coverage": "nyc -r lcov -n 'src/**/*' -n 'plugins/**/*' npm run coverage:tests",
"coverage:tests": "npm run test",
"codecov": "npm run coverage && codecov -t 411de6c7-82d2-41e9-a1cc-9096cdab6c72",
"lint": "eslint ./src"
},
"repository": {
"type": "git",
"url": "https://github.com/spencermountain/spacetime.git"
},
"files": [
"src",
"builds",
"api",
"types",
"zonefile"
],
"prettier": {
"trailingComma": "none",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 100
},
"devDependencies": {
"@rollup/plugin-commonjs": "^29.0.2",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-terser": "^1.0.0",
"eslint-plugin-regexp": "3.1.0",
"rollup": "4.62.2",
"shelljs": "0.10.0",
"tap-dancer": "0.3.4",
"tape": "5.10.2",
"timekeeper": "2.3.1"
},
"license": "Apache-2.0"
}

1
frontend/node_modules/spacetime/src/_version.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export default '7.13.0'

9
frontend/node_modules/spacetime/src/data/ampm.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
let morning = 'am'
let evening = 'pm'
export function am() { return morning }
export function pm() { return evening }
export function set(i18n) {
morning = i18n.am || morning
evening = i18n.pm || evening
}

View File

@@ -0,0 +1,9 @@
let titleCaseEnabled = true
export function useTitleCase() {
return titleCaseEnabled
}
export function set(val) {
titleCaseEnabled = val
}

23
frontend/node_modules/spacetime/src/data/days.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
let shortDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
let longDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']
export function short() { return shortDays }
export function long() { return longDays }
export function set(i18n) {
shortDays = i18n.short || shortDays
longDays = i18n.long || longDays
}
export const aliases = {
mo: 1,
tu: 2,
we: 3,
th: 4,
fr: 5,
sa: 6,
su: 7,
tues: 2,
weds: 3,
wedn: 3,
thur: 4,
thurs: 4
}

28
frontend/node_modules/spacetime/src/data/distance.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
let past = 'past'
let future = 'future'
let present = 'present'
let now = 'now'
let almost = 'almost'
let over = 'over'
let pastDistance = (value) => `${value} ago`
let futureDistance = (value) => `in ${value}`
export function pastDistanceString(value) { return pastDistance(value) }
export function futureDistanceString(value) { return futureDistance(value) }
export function pastString() { return past }
export function futureString() { return future }
export function presentString() { return present }
export function nowString() { return now }
export function almostString() { return almost }
export function overString() { return over }
export function set(i18n) {
pastDistance = i18n.pastDistance || pastDistance
futureDistance = i18n.futureDistance || futureDistance
past = i18n.past || past
future = i18n.future || future
present = i18n.present || present
now = i18n.now || now
almost = i18n.almost || almost
over = i18n.over || over
}

View File

@@ -0,0 +1,16 @@
const o = {
millisecond: 1
}
o.second = 1000
o.minute = 60000
o.hour = 3.6e6 // dst is supported post-hoc
o.day = 8.64e7 //
o.date = o.day
o.month = 8.64e7 * 29.5 //(average)
o.week = 6.048e8
o.year = 3.154e10 // leap-years are supported post-hoc
//add plurals
Object.keys(o).forEach(k => {
o[k + 's'] = o[k]
})
export default o

View File

@@ -0,0 +1,19 @@
const monthLengths = [
31, // January - 31 days
28, // February - 28 days in a common year and 29 days in leap years
31, // March - 31 days
30, // April - 30 days
31, // May - 31 days
30, // June - 30 days
31, // July - 31 days
31, // August - 31 days
30, // September - 30 days
31, // October - 31 days
30, // November - 30 days
31 // December - 31 days
]
export default monthLengths
// 28 - feb
// 30 - april, june, sept, nov
// 31 - jan, march, may, july, aug, oct, dec

49
frontend/node_modules/spacetime/src/data/months.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
let shortMonths = [
'jan',
'feb',
'mar',
'apr',
'may',
'jun',
'jul',
'aug',
'sep',
'oct',
'nov',
'dec'
]
let longMonths = [
'january',
'february',
'march',
'april',
'may',
'june',
'july',
'august',
'september',
'october',
'november',
'december'
]
function buildMapping() {
const obj = {
sep: 8 //support this format
}
for (let i = 0; i < shortMonths.length; i++) {
obj[shortMonths[i]] = i
}
for (let i = 0; i < longMonths.length; i++) {
obj[longMonths[i]] = i
}
return obj
}
export function short() { return shortMonths }
export function long() { return longMonths }
export function mapping() { return buildMapping() }
export function set(i18n) {
shortMonths = i18n.short || shortMonths
longMonths = i18n.long || longMonths
}

7
frontend/node_modules/spacetime/src/data/quarters.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
export default [
null,
[0, 1], //jan 1
[3, 1], //apr 1
[6, 1], //july 1
[9, 1] //oct 1
]

21
frontend/node_modules/spacetime/src/data/seasons.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
//https://www.timeanddate.com/calendar/aboutseasons.html
// Spring - from March 1 to May 31;
// Summer - from June 1 to August 31;
// Fall (autumn) - from September 1 to November 30; and,
// Winter - from December 1 to February 28 (February 29 in a leap year).
const north = [
['spring', 2, 1],
['summer', 5, 1],
['fall', 8, 1],
['autumn', 8, 1],
['winter', 11, 1] //dec 1
];
const south = [
['fall', 2, 1],
['autumn', 2, 1],
['winter', 5, 1],
['spring', 8, 1],
['summer', 11, 1] //dec 1
];
export default { north, south }

35
frontend/node_modules/spacetime/src/data/units.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
let units = {
second: 'second',
seconds: 'seconds',
minute: 'minute',
minutes: 'minutes',
hour: 'hour',
hours: 'hours',
day: 'day',
days: 'days',
month: 'month',
months: 'months',
year: 'year',
years: 'years',
};
export function unitsString(unit) {
return units[unit] || '';
}
export function set(i18n = {}) {
units = {
second: i18n.second || units.second,
seconds: i18n.seconds || units.seconds,
minute: i18n.minute || units.minute,
minutes: i18n.minutes || units.minutes,
hour: i18n.hour || units.hour,
hours: i18n.hours || units.hours,
day: i18n.day || units.day,
days: i18n.days || units.days,
month: i18n.month || units.month,
months: i18n.months || units.months,
year: i18n.year || units.year,
years: i18n.years || units.years,
};
}

89
frontend/node_modules/spacetime/src/fns.js generated vendored Normal file
View File

@@ -0,0 +1,89 @@
//git:blame @JuliasCaesar https://www.timeanddate.com/date/leapyear.html
export function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0 }
// unsurprisingly-nasty `typeof date` call
export function isDate(d) { return Object.prototype.toString.call(d) === '[object Date]' && !isNaN(d.valueOf()) }
export function isArray(input) { return Object.prototype.toString.call(input) === '[object Array]' }
export function isObject(input) { return Object.prototype.toString.call(input) === '[object Object]' }
export function isBoolean(input) { return Object.prototype.toString.call(input) === '[object Boolean]' }
export function zeroPad(str, len = 2) {
const pad = '0'
str = str + ''
return str.length >= len ? str : new Array(len - str.length + 1).join(pad) + str
}
export function titleCase(str) {
if (!str) {
return ''
}
return str[0].toUpperCase() + str.substr(1)
}
export function ordinal(i) {
const j = i % 10
const k = i % 100
if (j === 1 && k !== 11) {
return i + 'st'
}
if (j === 2 && k !== 12) {
return i + 'nd'
}
if (j === 3 && k !== 13) {
return i + 'rd'
}
return i + 'th'
}
//strip 'st' off '1st'..
export function toCardinal(str) {
str = String(str)
str = str.replace(/([0-9])(st|nd|rd|th)$/i, '$1')
return parseInt(str, 10)
}
//used mostly for cleanup of unit names, like 'months'
export function normalize(str = '') {
str = str.toLowerCase().trim()
str = str.replace(/ies$/, 'y') //'centuries'
str = str.replace(/s$/, '')
str = str.replace(/-/g, '')
if (str === 'day' || str === 'days') {
return 'date'
}
if (str === 'min' || str === 'mins') {
return 'minute'
}
return str
}
export function getEpoch(tmp) {
//support epoch
if (typeof tmp === 'number') {
return tmp
}
//suport date objects
if (isDate(tmp)) {
return tmp.getTime()
}
// support spacetime objects
if (tmp.epoch || tmp.epoch === 0) {
return tmp.epoch
}
return null
}
//make sure this input is a spacetime obj
export function beADate(d, s) {
if (isObject(d) === false) {
return s.clone().set(d)
}
return d
}
export function formatTimezone(offset, delimiter = '') {
const sign = offset > 0 ? '+' : '-'
const absOffset = Math.abs(offset)
const hours = zeroPad(parseInt('' + absOffset, 10))
const minutes = zeroPad((absOffset % 1) * 60)
return `${sign}${hours}${delimiter}${minutes}`
}

68
frontend/node_modules/spacetime/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,68 @@
import Spacetime from './spacetime.js'
import whereIts from './whereIts.js'
import version from './_version.js'
const main = (input, tz, options) => new Spacetime(input, tz, options)
// set all properties of a given 'today' object
const setToday = function (s) {
const today = s._today || {}
Object.keys(today).forEach((k) => {
s = s[k](today[k])
})
return s
}
//some helper functions on the main method
main.now = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s
}
main.today = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s.startOf('day')
}
main.tomorrow = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s.add(1, 'day').startOf('day')
}
main.yesterday = (tz, options) => {
let s = new Spacetime(new Date().getTime(), tz, options)
s = setToday(s)
return s.subtract(1, 'day').startOf('day')
}
main.fromUnixSeconds = (secs, tz, options) => {
return new Spacetime(secs * 1000, tz, options)
}
main.extend = function (obj = {}) {
Object.keys(obj).forEach((k) => {
Spacetime.prototype[k] = obj[k]
})
return this
}
main.timezones = function () {
const s = new Spacetime()
return s.timezones
}
main.max = function (tz, options) {
const s = new Spacetime(null, tz, options)
s.epoch = 8640000000000000
return s
}
main.min = function (tz, options) {
const s = new Spacetime(null, tz, options)
s.epoch = -8640000000000000
return s
}
//find tz by time
main.whereIts = whereIts
main.version = version
//aliases:
main.plugin = main.extend
export default main

View File

@@ -0,0 +1,80 @@
import walkTo from '../../methods/set/walk.js'
import { toCardinal } from '../../fns.js'
import { validate, parseTime, parseYear, parseMonth, parseOffset, parseTz } from './_parsers.js'
export default [
// =====
// y-m-d
// =====
//iso-this 1998-05-30T22:00:00:000Z, iso-that 2017-04-03T08:00:00-0700
// optionally supports Temporal fmt w/ [IANA]
{
reg: /^(-?0{0,2}[0-9]{3,4})-([0-9]{1,2})-([0-9]{1,2})[T| ]([0-9.:]+)(Z|[0-9-+:]+)?(\[.*?\])?(\[.*?\])?$/i,
parse: (s, m) => {
const obj = {
year: m[1],
month: parseInt(m[2], 10) - 1,
date: m[3]
}
if (validate(obj) === false) {
s.epoch = null
return s
}
// if iana code in brackets at the end, set the timezone
if (m[6]) {
const tz = parseTz(m[6])//TODO addme
if (tz) {
s = s.timezone(tz)
}
} else {
parseOffset(s, m[5])
}
// For now, ignore Temporal calendar info in m[7]..
walkTo(s, obj)
s = parseTime(s, m[4])
return s
}
},
//short-iso "2015-03-25" or "2015/03/25" or "2015/03/25 12:26:14 PM"
{
reg: /^([0-9]{4})[\-/. ]([0-9]{1,2})[\-/. ]([0-9]{1,2})( [0-9]{1,2}(:[0-9]{0,2})?(:[0-9]{0,3})? ?(am|pm)?)?$/i,
parse: (s, m) => {
const obj = {
year: m[1],
month: parseInt(m[2], 10) - 1,
date: parseInt(m[3], 10)
}
if (obj.month >= 12) {
//support yyyy/dd/mm (weird, but ok)
obj.date = parseInt(m[2], 10)
obj.month = parseInt(m[3], 10) - 1
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, m[4])
return s
}
},
//text-month "2015-feb-25"
{
reg: /^([0-9]{4})[\-/. ]([a-z]+)[\-/. ]([0-9]{1,2})( [0-9]{1,2}(:[0-9]{0,2})?(:[0-9]{0,3})? ?(am|pm)?)?$/i,
parse: (s, m) => {
const obj = {
year: parseYear(m[1], s._today),
month: parseMonth(m[2]),
date: toCardinal(m[3] || '')
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, m[4])
return s
}
}
]

View File

@@ -0,0 +1,92 @@
import walkTo from '../../methods/set/walk.js'
import { toCardinal } from '../../fns.js'
import { validate, parseTime, parseYear, parseMonth, parseOffset } from './_parsers.js'
export default [
// =====
// m-d-y
// =====
//mm/dd/yyyy - uk/canada "6/28/2019, 12:26:14 PM"
{
reg: /^([0-9]{1,2})[-/.]([0-9]{1,2})[\-/.]?([0-9]{4})?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2} ?(am|pm|gmt))?$/i,
parse: (s, arr) => {
let month = parseInt(arr[1], 10) - 1
let date = parseInt(arr[2], 10)
//support dd/mm/yyy
if (s.british || month >= 12) {
date = parseInt(arr[1], 10)
month = parseInt(arr[2], 10) - 1
}
const obj = {
date,
month,
year: parseYear(arr[3], s._today) || new Date().getFullYear()
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, arr[4])
return s
}
},
//alt short format - "feb-25-2015"
{
reg: /^([a-z]+)[\-/. ]([0-9]{1,2})[\-/. ]?([0-9]{4}|'[0-9]{2})?( [0-9]{1,2}(:[0-9]{0,2})?(:[0-9]{0,3})? ?(am|pm)?)?$/i,
parse: (s, arr) => {
const obj = {
year: parseYear(arr[3], s._today),
month: parseMonth(arr[1]),
date: toCardinal(arr[2] || '')
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, arr[4])
return s
}
},
//Long "Mar 25 2015"
//February 22, 2017 15:30:00
{
reg: /^([a-z]+) ([0-9]{1,2})( [0-9]{4})?( ([0-9:]+( ?am| ?pm| ?gmt)?))?$/i,
parse: (s, arr) => {
const obj = {
year: parseYear(arr[3], s._today),
month: parseMonth(arr[1]),
date: toCardinal(arr[2] || '')
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, arr[4])
return s
}
},
// 'Sun Mar 14 15:09:48 +0000 2021'
{
reg: /^([a-z]+) ([0-9]{1,2}) ([0-9]{1,2}:[0-9]{2}:?[0-9]{0,2})( \+[0-9]{4})?( [0-9]{4})?$/i,
parse: (s, arr) => {
const [, month, date, time, tz, year] = arr
const obj = {
year: parseYear(year, s._today),
month: parseMonth(month),
date: toCardinal(date || '')
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseOffset(s, tz)
s = parseTime(s, time)
return s
}
}
]

View File

@@ -0,0 +1,64 @@
import walkTo from '../../methods/set/walk.js'
import { toCardinal } from '../../fns.js'
import { validate, parseTime, parseYear, parseMonth } from './_parsers.js'
export default [
// =====
// d-m-y
// =====
//common british format - "25-feb-2015"
{
reg: /^([0-9]{1,2})[-/]([a-z]+)[\-/]?([0-9]{4})?$/i,
parse: (s, m) => {
const obj = {
year: parseYear(m[3], s._today),
month: parseMonth(m[2]),
date: toCardinal(m[1] || '')
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, m[4])
return s
}
},
// "25 Mar 2015"
{
reg: /^([0-9]{1,2})( [a-z]+)( [0-9]{4}| '[0-9]{2})? ?([0-9]{1,2}:[0-9]{2}:?[0-9]{0,2} ?(am|pm|gmt))?$/i,
parse: (s, m) => {
const obj = {
year: parseYear(m[3], s._today),
month: parseMonth(m[2]),
date: toCardinal(m[1])
}
if (!obj.month || validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, m[4])
return s
}
},
// 01-jan-2020
{
reg: /^([0-9]{1,2})[. \-/]([a-z]+)[. \-/]([0-9]{4})?( [0-9]{1,2}(:[0-9]{0,2})?(:[0-9]{0,3})? ?(am|pm)?)?$/i,
parse: (s, m) => {
const obj = {
date: Number(m[1]),
month: parseMonth(m[2]),
year: Number(m[3])
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = s.startOf('day')
s = parseTime(s, m[4])
return s
}
}
]

View File

@@ -0,0 +1,143 @@
import walkTo from '../../methods/set/walk.js'
import { validate, parseTime, parseYear, parseMonth } from './_parsers.js'
export default [
// =====
// no dates
// =====
// '2012-06' month-only
{
reg: /^([0-9]{4})[\-/]([0-9]{2})$/,
parse: (s, m) => {
const obj = {
year: m[1],
month: parseInt(m[2], 10) - 1,
date: 1
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, m[4])
return s
}
},
//February 2017 (implied date)
{
reg: /^([a-z]+) ([0-9]{4})$/i,
parse: (s, arr) => {
const obj = {
year: parseYear(arr[2], s._today),
month: parseMonth(arr[1]),
date: s._today.date || 1
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s, arr[4])
return s
}
},
{
// 'q2 2002'
reg: /^(q[0-9])( of)?( [0-9]{4})?/i,
parse: (s, arr) => {
const quarter = arr[1] || ''
s = s.quarter(quarter)
let year = arr[3] || ''
if (year) {
year = year.trim()
s = s.year(year)
}
return s
}
},
{
// 'summer 2002'
reg: /^(spring|summer|winter|fall|autumn)( of)?( [0-9]{4})?/i,
parse: (s, arr) => {
const season = arr[1] || ''
s = s.season(season)
let year = arr[3] || ''
if (year) {
year = year.trim()
s = s.year(year)
}
return s
}
},
{
// '200bc'
reg: /^[0-9,]+ ?b\.?c\.?$/i,
parse: (s, arr) => {
let str = arr[0] || ''
//make year-negative
str = str.replace(/^([0-9,]+) ?b\.?c\.?$/i, '-$1')
const d = new Date()
const obj = {
year: parseInt(str.trim(), 10),
month: d.getMonth(),
date: d.getDate()
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s)
return s
}
},
{
// '200ad'
reg: /^[0-9,]+ ?(a\.?d\.?|c\.?e\.?)$/i,
parse: (s, arr) => {
let str = arr[0] || ''
//remove commas
str = str.replace(/,/g, '')
const d = new Date()
const obj = {
year: parseInt(str.trim(), 10),
month: d.getMonth(),
date: d.getDate()
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s)
return s
}
},
{
// '1992'
reg: /^[0-9]{4}( ?a\.?d\.?)?$/i,
parse: (s, arr) => {
const today = s._today
// using today's date, but a new month is awkward.
if (today.month && !today.date) {
today.date = 1
}
const d = new Date()
const obj = {
year: parseYear(arr[0], today),
month: today.month || d.getMonth(),
date: today.date || d.getDate()
}
if (validate(obj) === false) {
s.epoch = null
return s
}
walkTo(s, obj)
s = parseTime(s)
return s
}
}
]

View File

@@ -0,0 +1,72 @@
import monthLengths from '../../data/monthLengths.js'
import { isLeapYear } from '../../fns.js'
import { mapping } from '../../data/months.js'
const months = mapping()
import parseOffset from './parseOffset.js'
import parseTime from './parseTime.js'
//given a month, return whether day number exists in it
const validate = (obj) => {
//invalid values
if (monthLengths.hasOwnProperty(obj.month) !== true) {
return false
}
//support leap-year in february
if (obj.month === 1) {
if (isLeapYear(obj.year) && obj.date <= 29) {
return true
} else {
return obj.date <= 28
}
}
//is this date too-big for this month?
const max = monthLengths[obj.month] || 0
if (obj.date <= max) {
return true
}
return false
}
const parseYear = (str = '', today) => {
str = str.trim()
// parse '86 shorthand
if (/^'[0-9][0-9]$/.test(str) === true) {
const num = Number(str.replace(/'/, ''))
if (num > 50) {
return 1900 + num
}
return 2000 + num
}
let year = parseInt(str, 10)
// use a given year from options.today
if (!year && today) {
year = today.year
}
// fallback to this year
year = year || new Date().getFullYear()
return year
}
const parseMonth = function (str) {
str = str.toLowerCase().trim()
if (str === 'sept') {
return months.sep
}
return months[str]
}
const parseTz = function (str) {
str = str.trim()
str = str.replace(/[[\]]/g, '')
return str
}
export {
parseOffset,
parseTime,
parseYear,
parseMonth,
validate,
parseTz
}

View File

@@ -0,0 +1,6 @@
import ymd from './01-ymd.js'
import mdy from './02-mdy.js'
import dmy from './03-dmy.js'
import misc from './04-misc.js'
export default [].concat(ymd, mdy, dmy, misc)

View File

@@ -0,0 +1,56 @@
//pull-apart ISO offsets, like "+0100"
const parseOffset = (s, offset) => {
if (!offset) {
return s
}
offset = offset.trim().toLowerCase()
// according to ISO8601, tz could be hh:mm, hhmm or hh
// so need few more steps before the calculation.
let num = 0
// for (+-)hh:mm
if (/^[+-]?[0-9]{2}:[0-9]{2}$/.test(offset)) {
//support "+01:00"
if (/:00/.test(offset) === true) {
offset = offset.replace(/:00/, '')
}
//support "+01:30"
if (/:30/.test(offset) === true) {
offset = offset.replace(/:30/, '.5')
}
}
// for (+-)hhmm
if (/^[+-]?[0-9]{4}$/.test(offset)) {
offset = offset.replace(/30$/, '.5')
}
num = parseFloat(offset)
//divide by 100 or 10 - , "+0100", "+01"
if (Math.abs(num) > 100) {
num = num / 100
}
//this is a fancy-move
if (num === 0 || offset === 'Z' || offset === 'z') {
s.tz = 'etc/gmt'
return s
}
//okay, try to match it to a utc timezone
//remember - this is opposite! a -5 offset maps to Etc/GMT+5 ¯\_(:/)_/¯
//https://askubuntu.com/questions/519550/why-is-the-8-timezone-called-gmt-8-in-the-filesystem
num *= -1
if (num >= 0) {
num = '+' + num
}
const tz = 'etc/gmt' + num
const zones = s.timezones
if (zones[tz]) {
// log a warning if we're over-writing a given timezone?
// console.log('changing timezone to: ' + tz)
s.tz = tz
}
return s
}
export default parseOffset

View File

@@ -0,0 +1,66 @@
// truncate any sub-millisecond values
const parseMs = function (str = '') {
str = String(str)
//js does not support sub-millisecond values
// so truncate these - 2021-11-02T19:55:30.087772
if (str.length > 3) {
str = str.substring(0, 3)
} else if (str.length === 1) {
// assume ms are zero-padded on the left
// but maybe not on the right.
// turn '.10' into '.100'
str = str + '00'
} else if (str.length === 2) {
str = str + '0'
}
return Number(str) || 0
}
const parseTime = (s, str = '') => {
// remove all whitespace
str = str.replace(/^\s+/, '').toLowerCase()
//formal time format - 04:30.23
let arr = str.match(/([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?[:.]?([0-9]{1,4})?/)
if (arr !== null) {
// eslint-disable-next-line prefer-const
let [, h, m, sec, ms] = arr
//validate it a little
h = Number(h)
if (h < 0 || h > 24) {
return s.startOf('day')
}
m = Number(m) //don't accept '5:3pm'
if (arr[2].length < 2 || m < 0 || m > 59) {
return s.startOf('day')
}
s = s.hour(h)
s = s.minute(m)
s = s.seconds(sec || 0)
s = s.millisecond(parseMs(ms))
//parse-out am/pm
const ampm = str.match(/[0-9] ?(am|pm)\b/)
if (ampm !== null && ampm[1]) {
s = s.ampm(ampm[1])
}
return s
}
//try an informal form - 5pm (no minutes)
arr = str.match(/([0-9]+) ?(am|pm)/)
if (arr !== null && arr[1]) {
const h = Number(arr[1])
//validate it a little..
if (h > 12 || h < 1) {
return s.startOf('day')
}
s = s.hour(arr[1] || 0)
s = s.ampm(arr[2])
s = s.startOf('hour')
return s
}
//no time info found, use start-of-day
s = s.startOf('day')
return s
}
export default parseTime

57
frontend/node_modules/spacetime/src/input/helpers.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
/* eslint-disable no-console */
const defaults = {
year: new Date().getFullYear(),
month: 0,
date: 1
}
const units = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']
//support [2016, 03, 01] format
const parseArray = (s, arr, today) => {
if (arr.length === 0) {
return s
}
for (let i = 0; i < units.length; i++) {
const num = arr[i] || today[units[i]] || defaults[units[i]] || 0
s = s[units[i]](num)
}
return s
}
//support {year:2016, month:3} format
const parseObject = (s, obj) => {
if (Object.keys(obj).length === 0) {
return s
}
obj = Object.assign({}, defaults, obj)
if (obj.timezone) {
s.tz = obj.timezone
}
for (let i = 0; i < units.length; i++) {
const unit = units[i]
if (obj[unit] !== undefined) {
s = s[unit](obj[unit])
}
}
return s
}
// this may seem like an arbitrary number, but it's 'within jan 1970'
// this is only really ambiguous until 2054 or so
const parseNumber = function (s, input) {
const minimumEpoch = 2500000000
// if the given epoch is really small, they've probably given seconds and not milliseconds
// anything below this number is likely (but not necessarily) a mistaken input.
if (input > 0 && input < minimumEpoch && s.silent === false) {
console.warn(' - Warning: You are setting the date to January 1970.')
console.warn(' - did input seconds instead of milliseconds?')
}
s.epoch = input
return s
}
export default {
parseArray,
parseObject,
parseNumber
}

78
frontend/node_modules/spacetime/src/input/index.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
import { isObject, isDate, isArray } from '../fns.js'
import fns from './helpers.js'
const { parseArray, parseObject, parseNumber } = fns
import namedDates from './named-dates.js'
import normalize from './normalize.js'
import parseString from './parse.js'
//we have to actually parse these inputs ourselves
// - can't use built-in js parser ;(
//=========================================
// ISO Date "2015-03-25"
// Short Date "03/25/2015" or "2015/03/25"
// Long Date "Mar 25 2015" or "25 Mar 2015"
// Full Date "Wednesday March 25 2015"
//=========================================
const defaults = {
year: new Date().getFullYear(),
month: 0,
date: 1
}
//find the epoch from different input styles
const parseInput = (s, input) => {
const today = s._today || defaults
//if we've been given a epoch number, it's easy
if (typeof input === 'number') {
return parseNumber(s, input)
}
//set tmp time
s.epoch = Date.now()
// overwrite tmp time with 'today' value, if exists
if (s._today && isObject(s._today) && Object.keys(s._today).length > 0) {
const res = parseObject(s, today)
if (res.isValid()) {
s.epoch = res.epoch
}
}
// null input means 'now'
if (input === null || input === undefined || input === '') {
return s //k, we're good.
}
//support input of Date() object
if (isDate(input) === true) {
s.epoch = input.getTime()
return s
}
//support [2016, 03, 01] format
if (isArray(input) === true) {
s = parseArray(s, input, today)
return s
}
//support {year:2016, month:3} format
if (isObject(input) === true) {
//support spacetime object as input
if (input.epoch) {
s.epoch = input.epoch
s.tz = input.tz
return s
}
const obj = Object.assign({}, today, input)
s = parseObject(s, obj)
return s
}
//input as a string..
if (typeof input !== 'string') {
return s
}
//little cleanup..
input = normalize(input)
//try some known-words, like 'now'
if (namedDates.hasOwnProperty(input) === true) {
s = namedDates[input](s)
return s
}
//try each text-parse template, use the first good result
return parseString(s, input)
}
export default parseInput

View File

@@ -0,0 +1,48 @@
// pull in 'today' data for the baseline moment
const getNow = function (s) {
s.epoch = Date.now()
Object.keys(s._today || {}).forEach((k) => {
if (typeof s[k] === 'function') {
s = s[k](s._today[k])
}
})
return s
}
const dates = {
now: (s) => {
return getNow(s)
},
today: (s) => {
return getNow(s)
},
tonight: (s) => {
s = getNow(s)
s = s.hour(18) //6pm
return s
},
tomorrow: (s) => {
s = getNow(s)
s = s.add(1, 'day')
s = s.startOf('day')
return s
},
yesterday: (s) => {
s = getNow(s)
s = s.subtract(1, 'day')
s = s.startOf('day')
return s
},
christmas: (s) => {
const year = getNow(s).year()
s = s.set([year, 11, 25, 18, 0, 0]) // Dec 25
return s
},
'new years': (s) => {
const year = getNow(s).year()
s = s.set([year, 11, 31, 18, 0, 0]) // Dec 31
return s
}
}
dates['new years eve'] = dates['new years']
export default dates

12
frontend/node_modules/spacetime/src/input/normalize.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
//little cleanup..
const normalize = function (str) {
// remove all day-names
str = str.replace(/\b(mon|tues?|wed|wednes|thur?s?|fri|sat|satur|sun)(day)?\b/i, '')
//remove ordinal ending
str = str.replace(/([0-9])(th|rd|st|nd)/, '$1')
str = str.replace(/,/g, '')
str = str.replace(/ +/g, ' ').trim()
return str
}
export default normalize

22
frontend/node_modules/spacetime/src/input/parse.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/* eslint-disable no-console */
import parsers from './formats/index.js'
const parseString = function (s, input, givenTz) {
// let parsers = s.parsers || []
//try each text-parse template, use the first good result
for (let i = 0; i < parsers.length; i++) {
const m = input.match(parsers[i].reg)
if (m) {
const res = parsers[i].parse(s, m, givenTz)
if (res !== null && res.isValid()) {
return res
}
}
}
if (s.silent === false) {
console.warn("Warning: couldn't parse date-string: '" + input + "'")
}
s.epoch = null
return s
}
export default parseString

241
frontend/node_modules/spacetime/src/methods.js generated vendored Normal file
View File

@@ -0,0 +1,241 @@
/* eslint-disable no-console */
import format from './methods/format/index.js'
import unixFmt from './methods/format/unixFmt.js'
import progress from './methods/progress.js'
import nearest from './methods/nearest.js'
import diff from './methods/diff/index.js'
import since from './methods/since/index.js'
import { startOf as _startOf, endOf as _endOf } from './methods/startOf.js'
import every from './methods/every.js'
import timezone from './timezone/index.js'
import findTz from './timezone/find.js'
import handleInput from './input/index.js'
import { isLeapYear } from './fns.js'
import { short, long } from './data/days.js'
const units = [
'century',
'decade',
'year',
'month',
'date',
'day',
'hour',
'minute',
'second',
'millisecond'
]
//the spacetime instance methods (also, the API)
const methods = {
set: function (input, tz) {
let s = this.clone()
s = handleInput(s, input, null)
if (tz) {
s.tz = findTz(tz, s.timezones)
}
return s
},
timezone: function (tz) {
// hot-swap the timezone, to avoid time-change
if (tz !== undefined) {
const json = this.json()
json.timezone = tz
return this.set(json, tz)
}
return timezone(this)
},
isDST: function () {
return timezone(this).current.isDST
},
hasDST: function () {
return timezone(this).hasDst
},
offset: function () {
return timezone(this).current.offset * 60
},
hemisphere: function () {
return timezone(this).hemisphere
},
format: function (fmt) {
return format(this, fmt)
},
unixFmt: function (fmt) {
return unixFmt(this, fmt)
},
startOf: function (unit) {
return _startOf(this, unit)
},
endOf: function (unit) {
return _endOf(this, unit)
},
leapYear: function () {
const year = this.year()
return isLeapYear(year)
},
progress: function (unit) {
return progress(this, unit)
},
nearest: function (unit) {
return nearest(this, unit)
},
diff: function (d, unit) {
return diff(this, d, unit)
},
since: function (d) {
if (!d) {
d = this.clone().set()
}
return since(this, d)
},
next: function (unit) {
const s = this.add(1, unit)
return s.startOf(unit)
},
//the start of the previous year/week/century
last: function (unit) {
const s = this.subtract(1, unit)
return s.startOf(unit)
},
isValid: function () {
//null/undefined epochs
if (!this.epoch && this.epoch !== 0) {
return false
}
return !isNaN(this.d.getTime())
},
//travel to this timezone
goto: function (tz) {
const s = this.clone()
s.tz = findTz(tz, s.timezones) //science!
return s
},
//get each week/month/day between a -> b
every: function (unit, to, stepCount) {
// allow swapping these params:
if (typeof unit === 'object' && typeof to === 'string') {
const tmp = to
to = unit
unit = tmp
}
return every(this, unit, to, stepCount)
},
isAwake: function () {
const hour = this.hour()
//10pm -> 8am
if (hour < 8 || hour > 22) {
return false
}
return true
},
isAsleep: function () {
return !this.isAwake()
},
daysInMonth: function () {
switch (this.month()) {
case 0:
return 31
case 1:
return this.leapYear() ? 29 : 28
case 2:
return 31
case 3:
return 30
case 4:
return 31
case 5:
return 30
case 6:
return 31
case 7:
return 31
case 8:
return 30
case 9:
return 31
case 10:
return 30
case 11:
return 31
default:
throw new Error('Invalid Month state.')
}
},
//pretty-printing
log: function () {
console.log('')
console.log(format(this, 'nice-short'))
return this
},
logYear: function () {
console.log('')
console.log(format(this, 'full-short'))
return this
},
json: function (input) {
// setter for json input
if (input !== undefined) {
let s = this.clone()
if (input.timezone) {
s.tz = input.timezone
}
for (let i = 0; i < units.length; i++) {
const unit = units[i]
if (input[unit] !== undefined) {
s = s[unit](input[unit])
}
}
return s
}
// produce json output
const obj = units.reduce((h, unit) => {
h[unit] = this[unit]()
return h
}, {})
obj.offset = this.timezone().current.offset
obj.timezone = this.tz
return obj
},
debug: function () {
const tz = this.timezone()
let date = this.format('MM') + ' ' + this.format('date-ordinal') + ' ' + this.year()
date += '\n - ' + this.format('time')
console.log('\n\n', date + '\n - ' + tz.name + ' (' + tz.current.offset + ')')
return this
},
//alias of 'since' but opposite - like moment.js
from: function (d) {
d = this.clone().set(d)
return d.since(this)
},
fromNow: function () {
const d = this.clone().set(Date.now())
return d.since(this)
},
weekStart: function (input) {
//accept a number directly
if (typeof input === 'number') {
this._weekStart = input
return this
}
if (typeof input === 'string') {
// accept 'wednesday'
input = input.toLowerCase().trim()
let num = short().indexOf(input)
if (num === -1) {
num = long().indexOf(input)
}
if (num === -1) {
num = 1 //go back to default
}
this._weekStart = num
} else {
console.warn('Spacetime Error: Cannot understand .weekStart() input:', input)
}
return this
}
}
// aliases
methods.inDST = methods.isDST
methods.round = methods.nearest
methods.each = methods.every
export default methods

178
frontend/node_modules/spacetime/src/methods/add.js generated vendored Normal file
View File

@@ -0,0 +1,178 @@
import walkTo from './set/walk.js'
import ms from '../data/milliseconds.js'
import { months, daysBack, days, getMonthLength } from './set/_model.js'
import { normalize } from '../fns.js'
// this logic is a bit of a mess,
// but briefly:
// millisecond-math, and some post-processing covers most-things
// we 'model' the calendar here only a little bit
// and that usually works-out...
const order = ['millisecond', 'second', 'minute', 'hour', 'date', 'month']
const keep = {
second: order.slice(0, 1),
minute: order.slice(0, 2),
quarterhour: order.slice(0, 2),
hour: order.slice(0, 3),
date: order.slice(0, 4),
month: order.slice(0, 4),
quarter: order.slice(0, 4),
season: order.slice(0, 4),
year: order,
decade: order,
century: order
}
keep.week = keep.hour
keep.season = keep.date
keep.quarter = keep.date
// Units need to be dst adjuested
const dstAwareUnits = {
year: true,
quarter: true,
season: true,
month: true,
week: true,
date: true
}
const keepDate = {
month: true,
quarter: true,
season: true,
year: true
}
const addMethods = (SpaceTime) => {
SpaceTime.prototype.add = function (num, unit) {
let s = this.clone()
if (!unit || num === 0) {
return s //don't bother
}
const old = this.clone()
unit = normalize(unit)
if (unit === 'millisecond') {
s.epoch += num
return s
}
// support 'fortnight' alias
if (unit === 'fortnight') {
num *= 2
unit = 'week'
}
//move forward by the estimated milliseconds (rough)
if (ms[unit]) {
s.epoch += ms[unit] * num
} else if (unit === 'week' || unit === 'weekend') {
s.epoch += ms.day * (num * 7)
} else if (unit === 'quarter' || unit === 'season') {
s.epoch += ms.month * (num * 3)
} else if (unit === 'quarterhour') {
s.epoch += ms.minute * 15 * num
}
//now ensure our milliseconds/etc are in-line
let want = {}
if (keep[unit]) {
keep[unit].forEach((u) => {
want[u] = old[u]()
})
}
if (dstAwareUnits[unit]) {
const diff = old.timezone().current.offset - s.timezone().current.offset
s.epoch += diff * 3600 * 1000
}
//ensure month/year has ticked-over
if (unit === 'month') {
want.month = old.month() + num
//month is the one unit we 'model' directly
want = months(want, old)
}
//support coercing a week, too
if (unit === 'week') {
const sum = old.date() + (num * 7)
if (sum <= 28 && sum > 1) {
want.date = sum
}
}
if (unit === 'weekend' && s.dayName() !== 'saturday') {
s = s.day('saturday', true) //ensure it's saturday
}
//support 25-hour day-changes on dst-changes
else if (unit === 'date') {
if (num < 0) {
want = daysBack(want, old, num)
} else {
//specify a naive date number, if it's easy to do...
const sum = old.date() + num
// ok, model this one too
want = days(want, old, sum)
}
//manually punt it if we haven't moved at all..
if (num !== 0 && old.isSame(s, 'day')) {
want.date = old.date() + num
}
}
// ensure a quarter is 3 months over
else if (unit === 'quarter') {
want.month = old.month() + (num * 3)
want.year = old.year()
// handle rollover
if (want.month < 0) {
const years = Math.floor(want.month / 12)
const remainder = want.month + (Math.abs(years) * 12)
want.month = remainder
want.year += years
} else if (want.month >= 12) {
const years = Math.floor(want.month / 12)
want.month = want.month % 12
want.year += years
}
want.date = old.date()
}
//ensure year has changed (leap-years)
else if (unit === 'year') {
const wantYear = old.year() + num
const haveYear = s.year()
if (haveYear < wantYear) {
const toAdd = Math.floor(num / 4) || 1 //approx num of leap-days
s.epoch += Math.abs(ms.day * toAdd)
} else if (haveYear > wantYear) {
const toAdd = Math.floor(num / 4) || 1 //approx num of leap-days
s.epoch += ms.day * toAdd
}
}
//these are easier
else if (unit === 'decade') {
want.year = s.year() + 10
} else if (unit === 'century') {
want.year = s.year() + 100
}
//keep current date, unless the month doesn't have it.
if (keepDate[unit]) {
const year = want.year !== undefined ? want.year : old.year()
const max = getMonthLength(want.month, year)
want.date = old.date()
if (want.date > max) {
want.date = max
}
}
if (Object.keys(want).length > 1) {
walkTo(s, want)
}
return s
}
//subtract is only add *-1
SpaceTime.prototype.subtract = function (num, unit) {
const s = this.clone()
return s.add(num * -1, unit)
}
//add aliases
SpaceTime.prototype.minus = SpaceTime.prototype.subtract
SpaceTime.prototype.plus = SpaceTime.prototype.add
}
export default addMethods

53
frontend/node_modules/spacetime/src/methods/compare.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
import { beADate, getEpoch } from '../fns.js'
const addMethods = SpaceTime => {
const methods = {
isAfter: function (d) {
d = beADate(d, this)
const epoch = getEpoch(d)
if (epoch === null) {
return null
}
return this.epoch > epoch
},
isBefore: function (d) {
d = beADate(d, this)
const epoch = getEpoch(d)
if (epoch === null) {
return null
}
return this.epoch < epoch
},
isEqual: function (d) {
d = beADate(d, this)
const epoch = getEpoch(d)
if (epoch === null) {
return null
}
return this.epoch === epoch
},
isBetween: function (start, end, isInclusive = false) {
start = beADate(start, this)
end = beADate(end, this)
const startEpoch = getEpoch(start)
if (startEpoch === null) {
return null
}
const endEpoch = getEpoch(end)
if (endEpoch === null) {
return null
}
if (isInclusive) {
return this.isBetween(start, end) || this.isEqual(start) || this.isEqual(end);
}
return startEpoch < this.epoch && this.epoch < endEpoch
}
}
//hook them into proto
Object.keys(methods).forEach(k => {
SpaceTime.prototype[k] = methods[k]
})
}
export default addMethods

View File

@@ -0,0 +1,44 @@
import { beADate, normalize } from '../../fns.js'
import waterfall from './waterfall.js'
const reverseDiff = function (obj) {
Object.keys(obj).forEach((k) => {
obj[k] *= -1
})
return obj
}
// this method counts a total # of each unit, between a, b.
// '1 month' means 28 days in february
// '1 year' means 366 days in a leap year
const main = function (a, b, unit) {
b = beADate(b, a)
//reverse values, if necessary
let reversed = false
if (a.isAfter(b)) {
const tmp = a
a = b
b = tmp
reversed = true
}
//compute them all (i know!)
let obj = waterfall(a, b)
if (reversed) {
obj = reverseDiff(obj)
}
//return just the requested unit
if (unit) {
//make sure it's plural-form
unit = normalize(unit)
if (/s$/.test(unit) !== true) {
unit += 's'
}
if (unit === 'dates') {
unit = 'days'
}
return obj[unit]
}
return obj
}
export default main

View File

@@ -0,0 +1,27 @@
//increment until dates are the same
const climb = (a, b, unit) => {
let i = 0
a = a.clone()
while (a.isBefore(b)) {
//do proper, expensive increment to catch all-the-tricks
a = a.add(1, unit)
i += 1
}
//oops, we went too-far..
if (a.isAfter(b, unit)) {
i -= 1
}
return i
}
// do a thurough +=1 on the unit, until they match
// for speed-reasons, only used on day, month, week.
const diffOne = (a, b, unit) => {
if (a.isBefore(b)) {
return climb(a, b, unit)
} else {
return climb(b, a, unit) * -1 //reverse it
}
}
export default diffOne

View File

@@ -0,0 +1,57 @@
import diffOne from './one.js'
// don't do anything too fancy here.
// 2020 - 2019 may be 1 year, or 0 years
// - '1 year difference' means 366 days during a leap year
const fastYear = (a, b) => {
let years = b.year() - a.year()
// should we decrement it by 1?
a = a.year(b.year())
if (a.isAfter(b)) {
years -= 1
}
return years
}
// use a waterfall-method for computing a diff of any 'pre-knowable' units
// compute years, then compute months, etc..
// ... then ms-math for any very-small units
const diff = function (a, b) {
// an hour is always the same # of milliseconds
// so these units can be 'pre-calculated'
const msDiff = b.epoch - a.epoch
const obj = {
milliseconds: msDiff,
seconds: parseInt(msDiff / 1000, 10)
}
obj.minutes = parseInt(obj.seconds / 60, 10)
obj.hours = parseInt(obj.minutes / 60, 10)
//do the year
let tmp = a.clone()
obj.years = fastYear(tmp, b)
tmp = a.add(obj.years, 'year')
//there's always 12 months in a year...
obj.months = obj.years * 12
tmp = a.add(obj.months, 'month')
obj.months += diffOne(tmp, b, 'month')
// there's always 4 quarters in a year...
obj.quarters = obj.years * 4
obj.quarters += parseInt((obj.months % 12) / 3, 10)
// there's always atleast 52 weeks in a year..
// (month * 4) isn't as close
obj.weeks = obj.years * 52
tmp = a.add(obj.weeks, 'week')
obj.weeks += diffOne(tmp, b, 'week')
// there's always atleast 7 days in a week
obj.days = obj.weeks * 7
tmp = a.add(obj.days, 'day')
obj.days += diffOne(tmp, b, 'day')
return obj
}
export default diff

54
frontend/node_modules/spacetime/src/methods/every.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import { normalize } from '../fns.js'
import { short, long } from '../data/days.js'
//is it 'wednesday'?
const isDay = function (unit) {
if (short().find((s) => s === unit)) {
return true
}
if (long().find((s) => s === unit)) {
return true
}
return false
}
// return a list of the weeks/months/days between a -> b
// returns spacetime objects in the timezone of the input
const every = function (start, unit, end, stepCount = 1) {
if (!unit || !end) {
return []
}
//cleanup unit param
unit = normalize(unit)
//cleanup to param
end = start.clone().set(end)
//swap them, if they're backwards
if (start.isAfter(end)) {
const tmp = start
start = end
end = tmp
}
//prevent going beyond end if unit/stepCount > than the range
if (start.diff(end, unit) < stepCount) {
return []
}
//support 'every wednesday'
let d = start.clone()
if (isDay(unit)) {
d = d.next(unit)
unit = 'week'
} else {
const first = d.startOf(unit)
if (first.isBefore(start)) {
d = d.next(unit)
}
}
//okay, actually start doing it
const result = []
while (d.isBefore(end)) {
result.push(d)
d = d.add(stepCount, unit)
}
return result
}
export default every

View File

@@ -0,0 +1,11 @@
import { formatTimezone } from '../../fns.js'
// create the timezone offset part of an iso timestamp
// it's kind of nuts how involved this is
// "+01:00", "+0100", or simply "+01"
const isoOffset = s => {
const offset = s.timezone().current.offset
return !offset ? 'Z' : formatTimezone(offset, ':')
}
export default isoOffset

View File

@@ -0,0 +1,224 @@
import { titleCase, zeroPad, ordinal } from '../../fns.js'
import { short } from '../../data/months.js'
import { short as _short } from '../../data/days.js'
import { useTitleCase } from '../../data/caseFormat.js'
import isoOffset from './_offset.js'
const applyCaseFormat = (str) => {
if (useTitleCase()) {
return titleCase(str)
}
return str
}
// iso-year padding
const padYear = (num) => {
if (num >= 0) {
return zeroPad(num, 4)
} else {
num = Math.abs(num)
return '-' + zeroPad(num, 4)
}
}
const format = {
day: (s) => applyCaseFormat(s.dayName()),
'day-short': (s) => applyCaseFormat(_short()[s.day()]),
'day-number': (s) => s.day(),
'day-ordinal': (s) => ordinal(s.day()),
'day-pad': (s) => zeroPad(s.day()),
date: (s) => s.date(),
'date-ordinal': (s) => ordinal(s.date()),
'date-pad': (s) => zeroPad(s.date()),
month: (s) => applyCaseFormat(s.monthName()),
'month-short': (s) => applyCaseFormat(short()[s.month()]),
'month-number': (s) => s.month(),
'month-ordinal': (s) => ordinal(s.month()),
'month-pad': (s) => zeroPad(s.month()),
'iso-month': (s) => zeroPad(s.month() + 1), //1-based months
year: (s) => {
let year = s.year()
if (year > 0) {
return year
}
year = Math.abs(year)
return year + ' BC'
},
'year-short': (s) => {
let year = s.year()
if (year > 0) {
return `'${String(s.year()).substr(2, 4)}`
}
year = Math.abs(year)
return year + ' BC'
},
'iso-year': (s) => {
const year = s.year()
const isNegative = year < 0
let str = zeroPad(Math.abs(year), 4) //0-padded
if (isNegative) {
//negative years are for some reason 6-digits ('-00008')
str = zeroPad(str, 6)
str = '-' + str
}
return str
},
time: (s) => s.time(),
'time-24': (s) => `${s.hour24()}:${zeroPad(s.minute())}`,
hour: (s) => s.hour12(),
'hour-pad': (s) => zeroPad(s.hour12()),
'hour-24': (s) => s.hour24(),
'hour-24-pad': (s) => zeroPad(s.hour24()),
minute: (s) => s.minute(),
'minute-pad': (s) => zeroPad(s.minute()),
second: (s) => s.second(),
'second-pad': (s) => zeroPad(s.second()),
millisecond: (s) => s.millisecond(),
'millisecond-pad': (s) => zeroPad(s.millisecond(), 3),
ampm: (s) => s.ampm(),
AMPM: (s) => s.ampm().toUpperCase(),
quarter: (s) => 'Q' + s.quarter(),
season: (s) => s.season(),
era: (s) => s.era(),
json: (s) => s.json(),
timezone: (s) => s.timezone().name,
offset: (s) => isoOffset(s),
numeric: (s) => `${s.year()}/${zeroPad(s.month() + 1)}/${zeroPad(s.date())}`, // yyyy/mm/dd
'numeric-us': (s) => `${zeroPad(s.month() + 1)}/${zeroPad(s.date())}/${s.year()}`, // mm/dd/yyyy
'numeric-uk': (s) => `${zeroPad(s.date())}/${zeroPad(s.month() + 1)}/${s.year()}`, //dd/mm/yyyy
'mm/dd': (s) => `${zeroPad(s.month() + 1)}/${zeroPad(s.date())}`, //mm/dd
// ... https://en.wikipedia.org/wiki/ISO_8601 ;(((
iso: (s) => {
const year = s.format('iso-year')
const month = zeroPad(s.month() + 1) //1-based months
const date = zeroPad(s.date())
const hour = zeroPad(s.h24())
const minute = zeroPad(s.minute())
const second = zeroPad(s.second())
const ms = zeroPad(s.millisecond(), 3)
const offset = isoOffset(s)
return `${year}-${month}-${date}T${hour}:${minute}:${second}.${ms}${offset}` //2018-03-09T08:50:00.000-05:00
},
'iso-short': (s) => {
const month = zeroPad(s.month() + 1) //1-based months
const date = zeroPad(s.date())
const year = padYear(s.year())
return `${year}-${month}-${date}` //2017-02-15
},
'iso-utc': (s) => {
return new Date(s.epoch).toISOString() //2017-03-08T19:45:28.367Z
},
'iso-full': (s) => {
let iso = s.format('iso')
const iana = s.timezone().name
if (iana) {
iso += `[${iana}]`
}
return iso
},
sql: (s) => {
const year = s.format('iso-year')
const month = zeroPad(s.month() + 1) //1-based months
const date = zeroPad(s.date())
const hour = zeroPad(s.h24())
const minute = zeroPad(s.minute())
const second = zeroPad(s.second())
return `${year}-${month}-${date} ${hour}:${minute}:${second}` //2017-03-08 19:45:28
},
//i made these up
nice: (s) => `${short()[s.month()]} ${ordinal(s.date())}, ${s.time()}`,
'nice-24': (s) =>
`${short()[s.month()]} ${ordinal(s.date())}, ${s.hour24()}:${zeroPad(
s.minute()
)}`,
'nice-year': (s) => `${short()[s.month()]} ${ordinal(s.date())}, ${s.year()}`,
'nice-day': (s) =>
`${_short()[s.day()]} ${applyCaseFormat(short()[s.month()])} ${ordinal(
s.date()
)}`,
'nice-full': (s) =>
`${s.dayName()} ${applyCaseFormat(s.monthName())} ${ordinal(s.date())}, ${s.time()}`,
'nice-full-24': (s) =>
`${s.dayName()} ${applyCaseFormat(s.monthName())} ${ordinal(
s.date()
)}, ${s.hour24()}:${zeroPad(s.minute())}`
}
//aliases
const aliases = {
'day-name': 'day',
'month-name': 'month',
'iso 8601': 'iso',
'iso 9075': 'sql',
'time-h24': 'time-24',
'time-12': 'time',
'time-h12': 'time',
tz: 'timezone',
iana: 'timezone',
'day-num': 'day-number',
'month-num': 'month-number',
'month-iso': 'iso-month',
'year-iso': 'iso-year',
'nice-short': 'nice',
'nice-short-24': 'nice-24',
mdy: 'numeric-us',
dmy: 'numeric-uk',
ymd: 'numeric',
'yyyy/mm/dd': 'numeric',
'mm/dd/yyyy': 'numeric-us',
'dd/mm/yyyy': 'numeric-us',
'little-endian': 'numeric-uk',
'big-endian': 'numeric',
'day-nice': 'nice-day'
}
Object.keys(aliases).forEach((k) => (format[k] = format[aliases[k]]))
const printFormat = (s, str = '') => {
//don't print anything if it's an invalid date
if (s.isValid() !== true) {
return ''
}
//support .format('month')
if (format.hasOwnProperty(str)) {
let out = format[str](s) || ''
if (str !== 'json') {
out = String(out)
if (str.toLowerCase() !== 'ampm') {
out = applyCaseFormat(out)
}
}
return out
}
//support '{hour}:{minute}' notation
if (str.indexOf('{') !== -1) {
const sections = /\{(.+?)\}/g
str = str.replace(sections, (_, fmt) => {
fmt = fmt.trim()
if (fmt !== 'AMPM') {
fmt = fmt.toLowerCase()
}
if (format.hasOwnProperty(fmt)) {
const out = String(format[fmt](s))
if (fmt.toLowerCase() !== 'ampm') {
return applyCaseFormat(out)
}
return out
}
return ''
})
return str
}
return s.format('iso-short')
}
export default printFormat

View File

@@ -0,0 +1,179 @@
import { formatTimezone, zeroPad as pad } from '../../fns.js'
//parse this insane unix-time-templating thing, from the 19th century
//http://unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns
//time-symbols we support
const mapping = {
G: (s) => s.era(),
GG: (s) => s.era(),
GGG: (s) => s.era(),
GGGG: (s) => (s.era() === 'AD' ? 'Anno Domini' : 'Before Christ'),
//year
y: (s) => s.year(),
yy: (s) => {
//last two chars
return pad(Number(String(s.year()).substr(2, 4)))
},
yyy: (s) => s.year(),
yyyy: (s) => s.year(),
yyyyy: (s) => '0' + s.year(),
// u: (s) => {},//extended non-gregorian years
//quarter
Q: (s) => s.quarter(),
QQ: (s) => s.quarter(),
QQQ: (s) => s.quarter(),
QQQQ: (s) => s.quarter(),
//month
M: (s) => s.month() + 1,
MM: (s) => pad(s.month() + 1),
MMM: (s) => s.format('month-short'),
MMMM: (s) => s.format('month'),
//week
w: (s) => s.week(),
ww: (s) => pad(s.week()),
//week of month
// W: (s) => s.week(),
//date of month
d: (s) => s.date(),
dd: (s) => pad(s.date()),
//date of year
D: (s) => s.dayOfYear(),
DD: (s) => pad(s.dayOfYear()),
DDD: (s) => pad(s.dayOfYear(), 3),
// F: (s) => {},//date of week in month
// g: (s) => {},//modified julian day
//day
E: (s) => s.format('day-short'),
EE: (s) => s.format('day-short'),
EEE: (s) => s.format('day-short'),
EEEE: (s) => s.format('day'),
EEEEE: (s) => s.format('day')[0],
e: (s) => s.day(),
ee: (s) => s.day(),
eee: (s) => s.format('day-short'),
eeee: (s) => s.format('day'),
eeeee: (s) => s.format('day')[0],
//am/pm
a: (s) => s.ampm().toUpperCase(),
aa: (s) => s.ampm().toUpperCase(),
aaa: (s) => s.ampm().toUpperCase(),
aaaa: (s) => s.ampm().toUpperCase(),
//hour
h: (s) => s.h12(),
hh: (s) => pad(s.h12()),
H: (s) => s.hour(),
HH: (s) => pad(s.hour()),
// j: (s) => {},//weird hour format
m: (s) => s.minute(),
mm: (s) => pad(s.minute()),
s: (s) => s.second(),
ss: (s) => pad(s.second()),
//milliseconds
SSS: (s) => pad(s.millisecond(), 3),
//milliseconds in the day
A: (s) => s.epoch - s.startOf('day').epoch,
//timezone
z: (s) => s.timezone().name,
zz: (s) => s.timezone().name,
zzz: (s) => s.timezone().name,
zzzz: (s) => s.timezone().name,
Z: (s) => formatTimezone(s.timezone().current.offset),
ZZ: (s) => formatTimezone(s.timezone().current.offset),
ZZZ: (s) => formatTimezone(s.timezone().current.offset),
ZZZZ: (s) => formatTimezone(s.timezone().current.offset, ':')
}
const addAlias = (char, to, n) => {
let name = char
let toName = to
for (let i = 0; i < n; i += 1) {
mapping[name] = mapping[toName]
name += char
toName += to
}
}
addAlias('q', 'Q', 4)
addAlias('L', 'M', 4)
addAlias('Y', 'y', 4)
addAlias('c', 'e', 4)
addAlias('k', 'H', 2)
addAlias('K', 'h', 2)
addAlias('S', 's', 2)
addAlias('v', 'z', 4)
addAlias('V', 'Z', 4)
// support unix-style escaping with ' character
const escapeChars = function (arr) {
for (let i = 0; i < arr.length; i += 1) {
if (arr[i] === `'`) {
// greedy-search for next apostrophe
for (let o = i + 1; o < arr.length; o += 1) {
if (arr[o]) {
arr[i] += arr[o]
}
if (arr[o] === `'`) {
arr[o] = null
break
}
arr[o] = null
}
}
}
return arr.filter((ch) => ch)
}
//combine consecutive chars, like 'yyyy' as one.
const combineRepeated = function (arr) {
for (let i = 0; i < arr.length; i += 1) {
const c = arr[i]
// greedy-forward
for (let o = i + 1; o < arr.length; o += 1) {
if (arr[o] === c) {
arr[i] += arr[o]
arr[o] = null
} else {
break
}
}
}
// '' means one apostrophe
arr = arr.filter((ch) => ch)
arr = arr.map((str) => {
if (str === `''`) {
str = `'`
}
return str
})
return arr
}
const unixFmt = (s, str) => {
let arr = str.split('')
// support character escaping
arr = escapeChars(arr)
//combine 'yyyy' as string.
arr = combineRepeated(arr)
return arr.reduce((txt, c) => {
if (mapping[c] !== undefined) {
txt += mapping[c](s) || ''
} else {
// 'unescape'
if (/^'.+'$/.test(c)) {
c = c.replace(/'/g, '')
}
txt += c
}
return txt
}, '')
}
export default unixFmt

51
frontend/node_modules/spacetime/src/methods/i18n.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
import { isObject, isBoolean } from '../fns.js'
import { set as setD } from '../data/days.js'
import { set as setM } from '../data/months.js'
import { set as setTcf } from '../data/caseFormat.js'
import { set as setAmpm } from '../data/ampm.js'
import { set as setDistance } from '../data/distance.js'
import { set as setUnits } from '../data/units.js'
const addMethods = SpaceTime => {
const methods = {
i18n: function (data) {
//change the day names
if (isObject(data.days)) {
setD(data.days)
}
//change the month names
if (isObject(data.months)) {
setM(data.months)
}
//change the display style of the month / day names
if (isBoolean(data.useTitleCase)) {
setTcf(data.useTitleCase)
}
//change am and pm strings
if (isObject(data.ampm)) {
setAmpm(data.ampm)
}
//change distance strings
if(isObject(data.distance)){
setDistance(data.distance)
}
//change units strings
if(isObject(data.units)){
setUnits(data.units)
}
return this
}
}
//hook them into proto
Object.keys(methods).forEach(k => {
SpaceTime.prototype[k] = methods[k]
})
}
export default addMethods

25
frontend/node_modules/spacetime/src/methods/nearest.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
/* eslint-disable no-console */
import { normalize } from '../fns.js'
//round to either current, or +1 of this unit
const nearest = (s, unit) => {
//how far have we gone?
const prog = s.progress()
unit = normalize(unit)
//fix camel-case for this one
if (unit === 'quarterhour') {
unit = 'quarterHour'
}
if (prog[unit] !== undefined) {
// go forward one?
if (prog[unit] > 0.5) {
s = s.add(1, unit)
}
// go to start
s = s.startOf(unit)
} else if (s.silent === false) {
console.warn("no known unit '" + unit + "'")
}
return s
}
export default nearest

View File

@@ -0,0 +1,25 @@
import { normalize } from '../fns.js'
const units = ['year', 'season', 'quarter', 'month', 'week', 'day', 'quarterHour', 'hour', 'minute']
const doUnit = function (s, k) {
const start = s.clone().startOf(k)
const end = s.clone().endOf(k)
const duration = end.epoch - start.epoch
const percent = (s.epoch - start.epoch) / duration
return parseFloat(percent.toFixed(2))
}
//how far it is along, from 0-1
const progress = (s, unit) => {
if (unit) {
unit = normalize(unit)
return doUnit(s, unit)
}
const obj = {}
units.forEach(k => {
obj[k] = doUnit(s, k)
})
return obj
}
export default progress

View File

@@ -0,0 +1,188 @@
import { milliseconds, seconds, minutes, hours, time as _time } from '../set/set.js'
import { am, pm } from '../../data/ampm.js'
import { zeroPad } from '../../fns.js'
const methods = {
millisecond: function (num) {
if (num !== undefined) {
const s = this.clone()
s.epoch = milliseconds(s, num)
return s
}
return this.d.getMilliseconds()
},
second: function (num, goFwd) {
if (num !== undefined) {
const s = this.clone()
s.epoch = seconds(s, num, goFwd)
return s
}
return this.d.getSeconds()
},
minute: function (num, goFwd) {
if (num !== undefined) {
const s = this.clone()
s.epoch = minutes(s, num, goFwd)
return s
}
return this.d.getMinutes()
},
hour: function (num, goFwd) {
const d = this.d
if (num !== undefined) {
const s = this.clone()
s.epoch = hours(s, num, goFwd)
return s
}
return d.getHours()
},
//'3:30' is 3.5
hourFloat: function (num, goFwd) {
if (num !== undefined) {
const s = this.clone()
let minute = num % 1
minute = minute * 60
const hour = parseInt(num, 10)
s.epoch = hours(s, hour, goFwd)
s.epoch = minutes(s, minute, goFwd)
return s
}
const d = this.d
const hour = d.getHours()
let minute = d.getMinutes()
minute = minute / 60
return hour + minute
},
// hour in 12h format
hour12: function (str, goFwd) {
const d = this.d
if (str !== undefined) {
const s = this.clone()
str = '' + str
const m = str.match(/^([0-9]+)(am|pm)$/)
if (m) {
let hour = parseInt(m[1], 10)
if (m[2] === 'pm') {
hour += 12
}
s.epoch = hours(s, hour, goFwd)
}
return s
}
//get the hour
let hour12 = d.getHours()
if (hour12 > 12) {
hour12 = hour12 - 12
}
if (hour12 === 0) {
hour12 = 12
}
return hour12
},
//some ambiguity here with 12/24h
time: function (str, goFwd) {
if (str !== undefined) {
const s = this.clone()
str = str.toLowerCase().trim()
s.epoch = _time(s, str, goFwd)
return s
}
return `${this.h12()}:${zeroPad(this.minute())}${this.ampm()}`
},
// either 'am' or 'pm'
ampm: function (input, goFwd) {
// let which = 'am'
let which = am()
let hour = this.hour()
if (hour >= 12) {
// which = 'pm'
which = pm()
}
if (typeof input !== 'string') {
return which
}
//okay, we're doing a setter
const s = this.clone()
input = input.toLowerCase().trim()
//ampm should never change the day
// - so use `.hour(n)` instead of `.minus(12,'hour')`
if (hour >= 12 && input === 'am') {
//noon is 12pm
hour -= 12
return s.hour(hour, goFwd)
}
if (hour < 12 && input === 'pm') {
hour += 12
return s.hour(hour, goFwd)
}
return s
},
//some hard-coded times of day, like 'noon'
dayTime: function (str, goFwd) {
if (str !== undefined) {
const times = {
morning: '7:00',
breakfast: '7:00',
noon: '12:00',
lunch: '12:00',
afternoon: '14:00',
evening: '18:00',
dinner: '18:00',
night: '23:00',
midnight: '00:00'
}
let s = this.clone()
str = str || ''
str = str.toLowerCase()
if (times.hasOwnProperty(str) === true) {
s = s.time(times[str], goFwd)
}
return s
}
const h = this.hour()
if (h < 6) {
return 'night'
}
if (h < 12) {
//until noon
return 'morning'
}
if (h < 17) {
//until 5pm
return 'afternoon'
}
if (h < 22) {
//until 10pm
return 'evening'
}
return 'night'
},
//get/set a traditional iso string
iso: function (num) {
if (num !== undefined) {
return this.set(num)
}
return this.format('iso')
},
// get/set a new iso string
isoFull: function (num) {
if (num !== undefined) {
return this.set(num)
}
return this.format('iso-full')
},
epochSeconds: function (num) {
if (num !== undefined) {
this.epoch = num * 1000
return this
}
return Math.floor(this.epoch / 1000)
}
}
export default methods

View File

@@ -0,0 +1,67 @@
import { date as _date } from '../set/set.js'
import { aliases, short, long } from '../../data/days.js'
import walkTo from '../set/walk.js'
const methods = {
// # day in the month
date: function (num, goFwd) {
if (num !== undefined) {
const s = this.clone()
num = parseInt(num, 10)
if (num) {
s.epoch = _date(s, num, goFwd)
}
return s
}
return this.d.getDate()
},
//like 'wednesday' (hard!)
day: function (input, goFwd) {
if (input === undefined) {
return this.d.getDay()
}
const original = this.clone()
let want = input
// accept 'wednesday'
if (typeof input === 'string') {
input = input.toLowerCase()
if (aliases.hasOwnProperty(input)) {
want = aliases[input]
} else {
want = short().indexOf(input)
if (want === -1) {
want = long().indexOf(input)
}
}
}
//move approx
const day = this.d.getDay()
let diff = day - want
if (goFwd === true && diff > 0) {
diff = diff - 7
}
if (goFwd === false && diff < 0) {
diff = diff + 7
}
const s = this.subtract(diff, 'days')
//tighten it back up
walkTo(s, {
hour: original.hour(),
minute: original.minute(),
second: original.second()
})
return s
},
//these are helpful name-wrappers
dayName: function (input, goFwd) {
if (input === undefined) {
return long()[this.day()]
}
let s = this.clone()
s = s.day(input, goFwd)
return s
}
}
export default methods

View File

@@ -0,0 +1,286 @@
/* eslint-disable no-console */
import { dayOfYear as _dayOfYear, week as setWeek, month as _month, year as _year } from '../set/set.js'
import { long } from '../../data/months.js'
import quarters from '../../data/quarters.js'
import seasons from '../../data/seasons.js'
import ms from '../../data/milliseconds.js'
const clearMinutes = (s) => {
s = s.minute(0)
s = s.second(0)
s = s.millisecond(1)
return s
}
const millennium = function (input) {
if (input !== undefined) {
if (typeof input === 'string') {
input = input.replace(/([0-9])(th|rd|st|nd)/, '$1') //fix ordinals
input = Number(input)
if (isNaN(input)) {
console.warn('Spacetime: Invalid millennium input')
return this
}
}
if (input > 0) {
input -= 1
}
let year = input * 1000
// there is no year 0
if (year === 0) {
year = 1
}
return this.year(year)
}
// get the current millennium
let num = Math.floor(this.year() / 1000)
if (num >= 0) {
num += 1
}
return num
}
const methods = {
// day 0-366
dayOfYear: function (num, goFwd) {
if (num !== undefined) {
const s = this.clone()
s.epoch = _dayOfYear(s, num, goFwd)
return s
}
//days since newyears - jan 1st is 1, jan 2nd is 2...
let sum = 0
const month = this.d.getMonth()
let tmp
//count the num days in each month
for (let i = 1; i <= month; i++) {
tmp = new Date()
tmp.setDate(1)
tmp.setFullYear(this.d.getFullYear()) //the year matters, because leap-years
tmp.setHours(1)
tmp.setMinutes(1)
tmp.setMonth(i)
tmp.setHours(-2) //the last day of the month
sum += tmp.getDate()
}
return sum + this.d.getDate()
},
//since the start of the year
week: function (num, goFwd) {
// week-setter
if (num !== undefined) {
let s = this.clone()
s = setWeek(s, num, goFwd)
s = clearMinutes(s)
return s
}
//find-out which week it is:
const thisOne = this.epoch
let tmp = this.clone()
// first - are we in week 1 of the next year?
if (tmp.monthName() === 'december' && tmp.date() >= 29) {
const startNext = setWeek(tmp.add(15, 'days'), 1, false)
if (startNext.epoch <= tmp.epoch) {
return 1
}
}
// Ok, calculate which week we're in:
// go to the first week of the year
tmp = tmp.month(0) // go to jan 1
tmp = tmp.date(1)
tmp = clearMinutes(tmp)
tmp = tmp.day('monday', false) // go backward to monday
if (tmp.monthName() === 'december' && tmp.date() < 29) {
tmp = tmp.add(1, 'week')
}
tmp = tmp.minus(2, 'hours') // fudge for any DST
//if the week technically hasn't started yet
if (tmp.epoch > thisOne) {
return 1
}
//speed it up, if we can
let i = 0
const skipWeeks = this.month() * 4
tmp.epoch += ms.week * skipWeeks
i += skipWeeks
for (; i <= 52; i++) {
if (tmp.epoch > thisOne) {
return i
}
tmp = tmp.add(1, 'week')
}
return 52
},
//either name or number
month: function (input, goFwd) {
if (input !== undefined) {
const s = this.clone()
s.epoch = _month(s, input, goFwd)
return s
}
return this.d.getMonth()
},
//'january'
monthName: function (input, goFwd) {
if (input !== undefined) {
let s = this.clone()
s = s.month(input, goFwd)
return s
}
return long()[this.month()]
},
//q1, q2, q3, q4
quarter: function (num, goFwd) {
if (num !== undefined) {
if (typeof num === 'string') {
num = num.replace(/^q/i, '')
num = parseInt(num, 10)
}
if (quarters[num]) {
let s = this.clone()
const month = quarters[num][0]
s = s.month(month, goFwd)
s = s.date(1, goFwd)
s = s.startOf('day')
return s
}
}
const month = this.d.getMonth()
for (let i = 1; i < quarters.length; i++) {
if (month < quarters[i][0]) {
return i - 1
}
}
return 4
},
//spring, summer, winter, fall
season: function (input, goFwd) {
let hem = 'north'
if (this.hemisphere() === 'South') {
hem = 'south'
}
if (input !== undefined) { // setter
let s = this.clone()
for (let i = 0; i < seasons[hem].length; i++) {
if (input === seasons[hem][i][0]) {
s = s.month(seasons[hem][i][1], goFwd)
s = s.date(1)
s = s.startOf('day')
}
}
return s
}
const month = this.d.getMonth()
for (let i = 0; i < seasons[hem].length - 1; i++) {
if (month >= seasons[hem][i][1] && month < seasons[hem][i + 1][1]) {
return seasons[hem][i][0]
}
}
return hem === 'north' ? 'winter' : 'summer'
},
//the year number
year: function (num) {
if (num !== undefined) {
const s = this.clone()
s.epoch = _year(s, num)
return s
}
return this.d.getFullYear()
},
//bc/ad years
era: function (str) {
if (str !== undefined) {
const s = this.clone()
str = str.toLowerCase()
//TODO: there is no year-0AD i think. may have off-by-1 error here
const year = s.d.getFullYear()
//make '1992' into 1992bc..
if (str === 'bc' && year > 0) {
s.epoch = _year(s, year * -1)
}
//make '1992bc' into '1992'
if (str === 'ad' && year < 0) {
s.epoch = _year(s, year * -1)
}
return s
}
if (this.d.getFullYear() < 0) {
return 'BC'
}
return 'AD'
},
// 2019 -> 2010
decade: function (input) {
if (input !== undefined) {
input = String(input)
input = input.replace(/([0-9])'?s$/, '$1') //1950's
input = input.replace(/([0-9])(th|rd|st|nd)/, '$1') //fix ordinals
if (!input) {
console.warn('Spacetime: Invalid decade input')
return this
}
// assume 20th century?? for '70s'.
if (input.length === 2 && /[0-9][0-9]/.test(input)) {
input = '19' + input
}
let year = Number(input)
if (isNaN(year)) {
return this
}
// round it down to the decade
year = Math.floor(year / 10) * 10
return this.year(year) //.startOf('decade')
}
return this.startOf('decade').year()
},
// 1950 -> 19+1
century: function (input) {
if (input !== undefined) {
if (typeof input === 'string') {
input = input.replace(/([0-9])(th|rd|st|nd)/, '$1') //fix ordinals
input = input.replace(/([0-9]+) ?(b\.?c\.?|a\.?d\.?)/i, (a, b, c) => {
if (c.match(/b\.?c\.?/i)) {
b = '-' + b
}
return b
})
input = input.replace(/c$/, '') //20thC
}
let year = Number(input)
if (isNaN(input)) {
console.warn('Spacetime: Invalid century input')
return this
}
// there is no century 0
if (year === 0) {
year = 1
}
if (year >= 0) {
year = (year - 1) * 100
} else {
year = (year + 1) * 100
}
return this.year(year)
}
// century getter
let num = this.startOf('century').year()
num = Math.floor(num / 100)
if (num < 0) {
return num - 1
}
return num + 1
},
// 2019 -> 2+1
millenium: millennium,
// alias without typo
millennium: millennium,
}
export default methods

View File

@@ -0,0 +1,24 @@
import timeFns from './01-time.js'
import dateFns from './02-date.js'
import yearFns from './03-year.js'
const methods = Object.assign({}, timeFns, dateFns, yearFns)
//aliases
methods.milliseconds = methods.millisecond
methods.seconds = methods.second
methods.minutes = methods.minute
methods.hours = methods.hour
methods.hour24 = methods.hour
methods.h12 = methods.hour12
methods.h24 = methods.hour24
methods.days = methods.day
const addMethods = Space => {
//hook the methods into prototype
Object.keys(methods).forEach(k => {
Space.prototype[k] = methods[k]
})
}
export default addMethods

63
frontend/node_modules/spacetime/src/methods/same.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
//make a string, for easy comparison between dates
const print = {
millisecond: (s) => {
return s.epoch
},
second: (s) => {
return [s.year(), s.month(), s.date(), s.hour(), s.minute(), s.second()].join('-')
},
minute: (s) => {
return [s.year(), s.month(), s.date(), s.hour(), s.minute()].join('-')
},
hour: (s) => {
return [s.year(), s.month(), s.date(), s.hour()].join('-')
},
day: (s) => {
return [s.year(), s.month(), s.date()].join('-')
},
week: (s) => {
return [s.year(), s.week()].join('-')
},
month: (s) => {
return [s.year(), s.month()].join('-')
},
quarter: (s) => {
return [s.year(), s.quarter()].join('-')
},
year: (s) => {
return s.year()
}
}
print.date = print.day
const addMethods = (SpaceTime) => {
SpaceTime.prototype.isSame = function (b, unit, tzAware = true) {
const a = this
if (!unit) {
return null
}
// support swapped params
if (typeof b === 'string' && typeof unit === 'object') {
const tmp = b
b = unit
unit = tmp
}
if (typeof b === 'string' || typeof b === 'number') {
b = new SpaceTime(b, this.timezone.name)
}
//support 'seconds' aswell as 'second'
unit = unit.replace(/s$/, '')
// make them the same timezone for proper comparison
if (tzAware === true && a.tz !== b.tz) {
b = b.clone()
b.tz = a.tz
}
if (print[unit]) {
return print[unit](a) === print[unit](b)
}
return null
}
}
export default addMethods

View File

@@ -0,0 +1,75 @@
import monthLength from '../../data/monthLengths.js'
import { isLeapYear } from '../../fns.js'
export const getMonthLength = function (month, year) {
if (month === 1 && isLeapYear(year)) {
return 29
}
return monthLength[month]
}
//month is the one thing we 'model/compute'
//- because ms-shifting can be off by enough
const rollMonth = (want, old) => {
//increment year
if (want.month > 0) {
const years = parseInt(want.month / 12, 10)
want.year = old.year() + years
want.month = want.month % 12
} else if (want.month < 0) {
const m = Math.abs(want.month)
let years = parseInt(m / 12, 10)
if (m % 12 !== 0) {
years += 1
}
want.year = old.year() - years
//ignore extras
want.month = want.month % 12
want.month = want.month + 12
if (want.month === 12) {
want.month = 0
}
}
return want
}
// briefly support day=-2 (this does not need to be perfect.)
const rollDaysDown = (want, old, sum) => {
want.year = old.year()
want.month = old.month()
const date = old.date()
want.date = date - Math.abs(sum)
while (want.date < 1) {
want.month -= 1
if (want.month < 0) {
want.month = 11
want.year -= 1
}
const max = getMonthLength(want.month, want.year)
want.date += max
}
return want
}
// briefly support day=33 (this does not need to be perfect.)
const rollDaysUp = (want, old, sum) => {
let year = old.year()
let month = old.month()
let max = getMonthLength(month, year)
while (sum > max) {
sum -= max
month += 1
if (month >= 12) {
month -= 12
year += 1
}
max = getMonthLength(month, year)
}
want.month = month
want.date = sum
return want
}
export const months = rollMonth
export const days = rollDaysUp
export const daysBack = rollDaysDown

280
frontend/node_modules/spacetime/src/methods/set/set.js generated vendored Normal file
View File

@@ -0,0 +1,280 @@
// javascript setX methods like setDate() can't be used because of the local bias
//these methods wrap around them.
import ms from '../../data/milliseconds.js'
import { mapping } from '../../data/months.js'
import monthLength from '../../data/monthLengths.js'
import walkTo from './walk.js'
import { isLeapYear } from '../../fns.js'
const validate = (n) => {
//handle number as a string
if (typeof n === 'string') {
n = parseInt(n, 10)
}
return n
}
const order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']
//reduce hostile micro-changes when moving dates by millisecond
const confirm = (s, tmp, unit) => {
const n = order.indexOf(unit)
const arr = order.slice(n, order.length)
for (let i = 0; i < arr.length; i++) {
const want = tmp[arr[i]]()
s[arr[i]](want)
}
return s
}
// allow specifying setter direction
const fwdBkwd = function (s, old, goFwd, unit) {
if (goFwd === true && s.isBefore(old)) {
s = s.add(1, unit)
} else if (goFwd === false && s.isAfter(old)) {
s = s.minus(1, unit)
}
return s
}
const milliseconds = function (s, n) {
n = validate(n)
const current = s.millisecond()
const diff = current - n //milliseconds to shift by
return s.epoch - diff
}
const seconds = function (s, n, goFwd) {
n = validate(n)
const old = s.clone()
const diff = s.second() - n
const shift = diff * ms.second
s.epoch = s.epoch - shift
s = fwdBkwd(s, old, goFwd, 'minute') // specify direction
return s.epoch
}
const minutes = function (s, n, goFwd) {
n = validate(n)
const old = s.clone()
const diff = s.minute() - n
const shift = diff * ms.minute
s.epoch -= shift
confirm(s, old, 'second')
s = fwdBkwd(s, old, goFwd, 'hour') // specify direction
return s.epoch
}
const hours = function (s, n, goFwd) {
n = validate(n)
if (n >= 24) {
n = 24
} else if (n < 0) {
n = 0
}
const old = s.clone()
let diff = s.hour() - n
let shift = diff * ms.hour
s.epoch -= shift
// oops, did we change the day?
if (s.date() !== old.date()) {
s = old.clone()
if (diff > 1) {
diff -= 1
}
if (diff < 1) {
diff += 1
}
shift = diff * ms.hour
s.epoch -= shift
}
walkTo(s, {
hour: n
})
confirm(s, old, 'minute')
s = fwdBkwd(s, old, goFwd, 'day') // specify direction
return s.epoch
}
const time = function (s, str, goFwd) {
let m = str.match(/([0-9]{1,2})[:h]([0-9]{1,2})(:[0-9]{1,2})? ?(am|pm)?/)
if (!m) {
//fallback to support just '2am'
m = str.match(/([0-9]{1,2}) ?(am|pm)/)
if (!m) {
return null // invalid time string - mark as invalid
}
m.splice(2, 0, '0') //add implicit 0 minutes
m.splice(3, 0, '') //add implicit seconds
}
let h24 = false
let hour = parseInt(m[1], 10)
let minute = parseInt(m[2], 10)
if (minute >= 60) {
minute = 59
}
if (hour > 12) {
h24 = true
}
//make the hour into proper 24h time
if (h24 === false) {
if (m[4] === 'am' && hour === 12) {
//12am is midnight
hour = 0
}
if (m[4] === 'pm' && hour < 12) {
//12pm is noon
hour += 12
}
}
// handle seconds
m[3] = m[3] || ''
m[3] = m[3].replace(/:/, '')
const sec = parseInt(m[3], 10) || 0
const old = s.clone()
s = s.hour(hour)
s = s.minute(minute)
s = s.second(sec)
s = s.millisecond(0)
s = fwdBkwd(s, old, goFwd, 'day') // specify direction
return s.epoch
}
const date = function (s, n, goFwd) {
n = validate(n)
//avoid setting february 31st
if (n > 28) {
const month = s.month()
let max = monthLength[month]
// support leap day in february
if (month === 1 && n === 29 && isLeapYear(s.year())) {
max = 29
}
if (n > max) {
n = max
}
}
//avoid setting < 0
if (n <= 0) {
n = 1
}
const old = s.clone()
walkTo(s, {
date: n
})
s = fwdBkwd(s, old, goFwd, 'month') // specify direction
return s.epoch
}
const month = function (s, n, goFwd) {
if (typeof n === 'string') {
if (n === 'sept') {
n = 'sep'
}
n = mapping()[n.toLowerCase()]
}
n = validate(n)
//don't go past december
if (n >= 12) {
n = 11
}
if (n <= 0) {
n = 0
}
let d = s.date()
//there's no 30th of february, etc.
if (d > monthLength[n]) {
//make it as close as we can..
d = monthLength[n]
}
const old = s.clone()
walkTo(s, {
month: n,
d
})
s = fwdBkwd(s, old, goFwd, 'year') // specify direction
return s.epoch
}
const year = function (s, n) {
// support '97
if (typeof n === 'string' && /^'[0-9]{2}$/.test(n)) {
n = n.replace(/'/, '').trim()
n = Number(n)
// '89 is 1989
if (n > 30) {
//change this in 10y
n = 1900 + n
} else {
// '12 is 2012
n = 2000 + n
}
}
n = validate(n)
walkTo(s, {
year: n
})
return s.epoch
}
const week = function (s, n, goFwd) {
const old = s.clone()
n = validate(n)
// don't set week=1, if we're already week=1 in late december
// because this could send us to another year
if (n === 1) {
if (s.monthName() === 'december' && s.date() >= 29) {
if (s.week() === 1) {
return s
}
}
}
// get the first week of the year
s = s.month(0)
s = s.date(1)
s = s.day('monday', false)//go backwards to monday
// did we go back too far?
if (s.monthName() === 'december' && s.date() < 29) {
s = s.add(1, 'week')
}
n -= 1 //1-based
s = s.add(n, 'weeks')
s = fwdBkwd(s, old, goFwd, 'year') // specify direction
return s
}
const dayOfYear = function (s, n, goFwd) {
n = validate(n)
const old = s.clone()
n -= 1 //days are 1-based
if (n <= 0) {
n = 0
} else if (n >= 365) {
if (isLeapYear(s.year())) {
n = 365
} else {
n = 364
}
}
s = s.startOf('year')
s = s.add(n, 'day')
confirm(s, old, 'hour')
s = fwdBkwd(s, old, goFwd, 'year') // specify direction
return s.epoch
}
export {
milliseconds,
seconds,
minutes,
hours,
time,
date,
month,
year,
week,
dayOfYear,
}

131
frontend/node_modules/spacetime/src/methods/set/walk.js generated vendored Normal file
View File

@@ -0,0 +1,131 @@
/* eslint-disable no-console */
import ms from '../../data/milliseconds.js'
//basically, step-forward/backward until js Date object says we're there.
const walk = (s, n, fn, unit, previous) => {
const current = s.d[fn]()
if (current === n) {
return //already there
}
const startUnit = previous === null ? null : s.d[previous]()
const original = s.epoch
//try to get it as close as we can
const diff = n - current
s.epoch += ms[unit] * diff
//DST edge-case: if we are going many days, be a little conservative
// console.log(unit, diff)
if (unit === 'day') {
// s.epoch -= ms.minute
//but don't push it over a month
if (Math.abs(diff) > 28 && n < 28) {
s.epoch += ms.hour
}
}
// 1st time: oops, did we change previous unit? revert it.
if (previous !== null && startUnit !== s.d[previous]()) {
// console.warn('spacetime warning: missed setting ' + unit)
s.epoch = original
// s.epoch += ms[unit] * diff * 0.89 // maybe try and make it close...?
}
//repair it if we've gone too far or something
//(go by half-steps, just in case)
const halfStep = ms[unit] / 2
while (s.d[fn]() < n) {
s.epoch += halfStep
}
while (s.d[fn]() > n) {
s.epoch -= halfStep
}
// 2nd time: did we change previous unit? revert it.
if (previous !== null && startUnit !== s.d[previous]()) {
// console.warn('spacetime warning: missed setting ' + unit)
s.epoch = original
}
}
//find the desired date by a increment/check while loop
const units = {
year: {
valid: (n) => n > -4000 && n < 4000,
walkTo: (s, n) => walk(s, n, 'getFullYear', 'year', null)
},
month: {
valid: (n) => n >= 0 && n <= 11,
walkTo: (s, n) => {
const d = s.d
const current = d.getMonth()
const original = s.epoch
const startUnit = d.getFullYear()
if (current === n) {
return
}
//try to get it as close as we can..
const diff = n - current
s.epoch += ms.day * (diff * 28) //special case
//oops, did we change the year? revert it.
if (startUnit !== s.d.getFullYear()) {
s.epoch = original
}
//increment by day
while (s.d.getMonth() < n) {
s.epoch += ms.day
}
while (s.d.getMonth() > n) {
s.epoch -= ms.day
}
}
},
date: {
valid: (n) => n > 0 && n <= 31,
walkTo: (s, n) => walk(s, n, 'getDate', 'day', 'getMonth')
},
hour: {
valid: (n) => n >= 0 && n < 24,
walkTo: (s, n) => walk(s, n, 'getHours', 'hour', 'getDate')
},
minute: {
valid: (n) => n >= 0 && n < 60,
walkTo: (s, n) => walk(s, n, 'getMinutes', 'minute', 'getHours')
},
second: {
valid: (n) => n >= 0 && n < 60,
walkTo: (s, n) => {
//do this one directly
s.epoch = s.seconds(n).epoch
}
},
millisecond: {
valid: (n) => n >= 0 && n < 1000,
walkTo: (s, n) => {
//do this one directly
s.epoch = s.milliseconds(n).epoch
}
}
}
const walkTo = (s, wants) => {
const keys = Object.keys(units)
const old = s.clone()
for (let i = 0; i < keys.length; i++) {
const k = keys[i]
let n = wants[k]
if (n === undefined) {
n = old[k]()
}
if (typeof n === 'string') {
n = parseInt(n, 10)
}
//make-sure it's valid
if (!units[k].valid(n)) {
s.epoch = null
if (s.silent === false) {
console.warn('invalid ' + k + ': ' + n)
}
return
}
units[k].walkTo(s, n)
}
return
}
export default walkTo

View File

@@ -0,0 +1,28 @@
/*
ISO 8601 duration format
// https://en.wikipedia.org/wiki/ISO_8601#Durations
"P3Y6M4DT12H30M5S"
P the start of the duration representation.
Y the number of years.
M the number of months.
W the number of weeks.
D the number of days.
T of the representation.
H the number of hours.
M the number of minutes.
S the number of seconds.
*/
const fmt = (n) => Math.abs(n) || 0
const toISO = function (diff) {
let iso = 'P'
iso += fmt(diff.years) + 'Y'
iso += fmt(diff.months) + 'M'
iso += fmt(diff.days) + 'DT'
iso += fmt(diff.hours) + 'H'
iso += fmt(diff.minutes) + 'M'
iso += fmt(diff.seconds) + 'S'
return iso
}
export default toISO

View File

@@ -0,0 +1,34 @@
//get number of hours/minutes... between the two dates
function getDiff(a, b) {
const isBefore = a.isBefore(b)
const later = isBefore ? b : a
let earlier = isBefore ? a : b
earlier = earlier.clone()
const diff = {
years: 0,
months: 0,
days: 0,
hours: 0,
minutes: 0,
seconds: 0
}
Object.keys(diff).forEach((unit) => {
if (earlier.isSame(later, unit)) {
return
}
const max = earlier.diff(later, unit)
earlier = earlier.add(max, unit)
diff[unit] = max
})
//reverse it, if necessary
if (isBefore) {
Object.keys(diff).forEach((u) => {
if (diff[u] !== 0) {
diff[u] *= -1
}
})
}
return diff
}
export default getDiff

View File

@@ -0,0 +1,64 @@
import { beADate } from '../../fns.js'
import toISO from './_iso.js'
import getDiff from './getDiff.js'
import soften from './soften.js'
import {
pastString,
futureString,
nowString,
presentString,
pastDistanceString,
futureDistanceString
} from "../../data/distance.js";
//by spencermountain + Shaun Grady
//create the human-readable diff between the two dates
const since = (start, end) => {
end = beADate(end, start)
const diff = getDiff(start, end)
const isNow = Object.keys(diff).every((u) => !diff[u])
if (isNow === true) {
return {
diff,
rounded: nowString(),
qualified: nowString(),
precise: nowString(),
abbreviated: [],
iso: 'P0Y0M0DT0H0M0S',
direction: presentString(),
}
}
let precise
let direction = futureString()
let { rounded, qualified } = soften(diff)
const { englishValues, abbreviated } = soften(diff)
//make them into a string
precise = englishValues.splice(0, 2).join(', ')
//handle before/after logic
if (start.isAfter(end) === true) {
rounded = pastDistanceString(rounded)
qualified = pastDistanceString(qualified)
precise = pastDistanceString(precise)
direction = pastString()
} else {
rounded = futureDistanceString(rounded)
qualified = futureDistanceString(qualified)
precise = futureDistanceString(precise)
}
// https://en.wikipedia.org/wiki/ISO_8601#Durations
// P[n]Y[n]M[n]DT[n]H[n]M[n]S
const iso = toISO(diff)
return {
diff,
rounded,
qualified,
precise,
abbreviated,
iso,
direction,
}
}
export default since

View File

@@ -0,0 +1,70 @@
//our conceptual 'break-points' for each unit
import { unitsString } from "../../data/units.js";
import { almostString, overString } from "../../data/distance.js";
const qualifiers = {
months: {
almost: 10,
over: 4
},
days: {
almost: 25,
over: 10
},
hours: {
almost: 20,
over: 8
},
minutes: {
almost: 50,
over: 20
},
seconds: {
almost: 50,
over: 20
}
}
// Expects a plural unit arg
function pluralize(value, unit) {
if (value === 1) {
return value + ' ' + unitsString(unit.slice(0, -1))
}
return value + ' ' + unitsString(unit)
}
const toSoft = function (diff) {
let rounded = null
let qualified = null
const abbreviated = []
const englishValues = []
//go through each value and create its text-representation
Object.keys(diff).forEach((unit, i, units) => {
const value = Math.abs(diff[unit])
if (value === 0) {
return
}
abbreviated.push(value + unit[0])
const englishValue = pluralize(value, unit)
englishValues.push(englishValue)
if (!rounded) {
rounded = englishValue
qualified = englishValue
if (i > 4) {
return
}
//is it a 'almost' something, etc?
const nextUnit = units[i + 1]
const nextValue = Math.abs(diff[nextUnit])
if (nextValue > qualifiers[nextUnit].almost) {
rounded = pluralize(value + 1, unit)
qualified = almostString() + ' ' + rounded
} else if (nextValue > qualifiers[nextUnit].over) {
qualified = overString() + ' ' + englishValue
}
}
})
return { qualified, rounded, abbreviated, englishValues }
}
export default toSoft

177
frontend/node_modules/spacetime/src/methods/startOf.js generated vendored Normal file
View File

@@ -0,0 +1,177 @@
import seasons from '../data/seasons.js'
import quarters from '../data/quarters.js'
import walkTo from './set/walk.js'
import { normalize } from '../fns.js'
const units = {
second: (s) => {
walkTo(s, {
millisecond: 0
})
return s
},
minute: (s) => {
walkTo(s, {
second: 0,
millisecond: 0
})
return s
},
quarterhour: (s) => {
const minute = s.minutes()
if (minute >= 45) {
s = s.minutes(45)
} else if (minute >= 30) {
s = s.minutes(30)
} else if (minute >= 15) {
s = s.minutes(15)
} else {
s = s.minutes(0)
}
walkTo(s, {
second: 0,
millisecond: 0
})
return s
},
hour: (s) => {
walkTo(s, {
minute: 0,
second: 0,
millisecond: 0
})
return s
},
day: (s) => {
walkTo(s, {
hour: 0,
minute: 0,
second: 0,
millisecond: 0
})
return s
},
week: (s) => {
const original = s.clone()
s = s.day(s._weekStart) //monday
if (s.isAfter(original)) {
s = s.subtract(1, 'week')
}
walkTo(s, {
hour: 0,
minute: 0,
second: 0,
millisecond: 0
})
return s
},
month: (s) => {
walkTo(s, {
date: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0
})
return s
},
quarter: (s) => {
const q = s.quarter()
if (quarters[q]) {
walkTo(s, {
month: quarters[q][0],
date: quarters[q][1],
hour: 0,
minute: 0,
second: 0,
millisecond: 0
})
}
return s
},
season: (s) => {
const current = s.season()
let hem = 'north'
if (s.hemisphere() === 'South') {
hem = 'south'
}
for (let i = 0; i < seasons[hem].length; i++) {
if (seasons[hem][i][0] === current) {
//winter goes between years
let year = s.year()
if (current === 'winter' && s.month() < 3) {
year -= 1
}
walkTo(s, {
year,
month: seasons[hem][i][1],
date: seasons[hem][i][2],
hour: 0,
minute: 0,
second: 0,
millisecond: 0
})
return s
}
}
return s
},
year: (s) => {
walkTo(s, {
month: 0,
date: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0
})
return s
},
decade: (s) => {
s = s.startOf('year')
const year = s.year()
const decade = parseInt(year / 10, 10) * 10
s = s.year(decade)
return s
},
century: (s) => {
s = s.startOf('year')
const year = s.year()
// near 0AD goes '-1 | +1'
const decade = parseInt(year / 100, 10) * 100
s = s.year(decade)
return s
}
}
units.date = units.day
const startOf = (a, unit) => {
let s = a.clone()
unit = normalize(unit)
if (units[unit]) {
return units[unit](s)
}
if (unit === 'summer' || unit === 'winter') {
s = s.season(unit)
return units.season(s)
}
return s
}
//piggy-backs off startOf
const endOf = (a, unit) => {
let s = a.clone()
unit = normalize(unit)
if (units[unit]) {
// go to beginning, go to next one, step back 1ms
s = units[unit](s) // startof
s = s.add(1, unit)
s = s.subtract(1, 'millisecond')
return s
}
return s
}
export {
startOf,
endOf
}

109
frontend/node_modules/spacetime/src/spacetime.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
import quickOffset from './timezone/quick.js'
import findTz from './timezone/find.js'
import handleInput from './input/index.js'
import methods from './methods.js'
import zones from '../zonefile/unpack.js'
import queryFns from './methods/query/index.js'
import addFns from './methods/add.js'
import sameFns from './methods/same.js'
import compareFns from './methods/compare.js'
import i18nFns from './methods/i18n.js'
let timezones = zones
// fake timezone-support, for fakers (es5 class)
const SpaceTime = function (input, tz, options = {}) {
// the holy moment
this.epoch = null
// the shift for the given timezone
this.tz = findTz(tz, timezones)
// whether to output warnings to console
this.silent = typeof options.silent !== 'undefined' ? options.silent : true
// favour british interpretation of 02/02/2018, etc
this.british = options.dmy || options.british
// does the week start on sunday, or monday:
this._weekStart = 1 // default to monday
if (options.weekStart !== undefined) {
this._weekStart = options.weekStart
}
// the reference today date object, (for testing)
this._today = {}
if (options.today !== undefined) {
this._today = options.today
}
// dunno if this is a good idea, or not
// Object.defineProperty(this, 'parsers', {
// enumerable: false,
// writable: true,
// value: parsers
// })
// add getter/setters
Object.defineProperty(this, 'd', {
// return a js date object
get: function () {
const offset = quickOffset(this)
// every computer is somewhere- get this computer's built-in offset
const bias = new Date(this.epoch).getTimezoneOffset() || 0
// movement
let shift = bias + (offset * 60) //in minutes
shift = shift * 60 * 1000 //in ms
// remove this computer's offset
const epoch = this.epoch + shift
const d = new Date(epoch)
return d
}
})
// add this data on the object, to allow adding new timezones
Object.defineProperty(this, 'timezones', {
get: () => timezones,
set: (obj) => {
timezones = obj
return obj
}
})
// parse the various formats
const tmp = handleInput(this, input)
this.epoch = tmp.epoch
if (tmp.tz) {
this.tz = tmp.tz
}
}
// (add instance methods to prototype)
Object.keys(methods).forEach((k) => {
SpaceTime.prototype[k] = methods[k]
})
// ¯\_(ツ)_/¯
SpaceTime.prototype.clone = function () {
return new SpaceTime(this.epoch, this.tz, {
silent: this.silent,
weekStart: this._weekStart,
today: this._today,
parsers: this.parsers
})
}
/**
* @deprecated use toNativeDate()
* @returns native date object at the same epoch
*/
SpaceTime.prototype.toLocalDate = function () {
return this.toNativeDate()
}
/**
* @returns native date object at the same epoch
*/
SpaceTime.prototype.toNativeDate = function () {
return new Date(this.epoch)
}
// append more methods
queryFns(SpaceTime)
addFns(SpaceTime)
sameFns(SpaceTime)
compareFns(SpaceTime)
i18nFns(SpaceTime)
export default SpaceTime

72
frontend/node_modules/spacetime/src/timezone/find.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
/* eslint-disable no-console */
import tzs from '../../zonefile/unpack.js'
import guessTz from './guessTz.js'
import parseOffset from './parseOffset.js'
let local = guessTz()
//add all the city names by themselves
const cities = Object.keys(tzs).reduce((h, k) => {
let city = k.split('/')[1] || ''
city = city.replace(/_/g, ' ')
h[city] = k
return h
}, {})
//try to match these against iana form
const normalize = (tz) => {
tz = tz.replace(/ time/g, '')
tz = tz.replace(/ (standard|daylight|summer)/g, '')
tz = tz.replace(/\b(east|west|north|south)ern/g, '$1')
tz = tz.replace(/\b(africa|america|australia)n/g, '$1')
tz = tz.replace(/\beuropean/g, 'europe')
tz = tz.replace(/islands/g, 'island')
return tz
}
// try our best to reconcile the timzone to this given string
const lookupTz = (str, zones) => {
if (!str) {
// guard if Intl response is unsupported (#397)
if (!zones.hasOwnProperty(local)) {
console.warn(`Unrecognized IANA id '${local}'. Setting fallback tz to UTC.`)
local = 'utc'
}
return local
}
if (typeof str !== 'string') {
console.error("Timezone must be a string - recieved: '", str, "'\n")
}
let tz = str.trim()
// let split = str.split('/')
//support long timezones like 'America/Argentina/Rio_Gallegos'
// if (split.length > 2 && zones.hasOwnProperty(tz) === false) {
// tz = split[0] + '/' + split[1]
// }
tz = tz.toLowerCase()
if (zones.hasOwnProperty(tz) === true) {
return tz
}
//lookup more loosely..
tz = normalize(tz)
if (zones.hasOwnProperty(tz) === true) {
return tz
}
//try city-names
if (cities.hasOwnProperty(tz) === true) {
return cities[tz]
}
// //try to parse '-5h'
if (/[0-9]/.test(tz) === true) {
const id = parseOffset(tz)
if (id) {
return id
}
}
throw new Error(
"Spacetime: Cannot find timezone named: '" + str + "'. Please enter an IANA timezone id."
)
}
export default lookupTz

View File

@@ -0,0 +1,30 @@
//find the implicit iana code for this machine.
//safely query the Intl object
//based on - https://bitbucket.org/pellepim/jstimezonedetect/src
const fallbackTZ = 'utc' //
//this Intl object is not supported often, yet
const safeIntl = () => {
if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') {
return null
}
const format = Intl.DateTimeFormat()
if (typeof format === 'undefined' || typeof format.resolvedOptions === 'undefined') {
return null
}
const timezone = format.resolvedOptions().timeZone
if (!timezone) {
return null
}
return timezone.toLowerCase()
}
const guessTz = () => {
const timezone = safeIntl()
if (timezone === null) {
return fallbackTZ
}
return timezone
}
//do it once per computer
export default guessTz

92
frontend/node_modules/spacetime/src/timezone/index.js generated vendored Normal file
View File

@@ -0,0 +1,92 @@
/* eslint-disable no-console */
import findTz from './find.js'
import inSummerTime from './summerTime.js'
const parseDst = dst => {
if (!dst) {
return []
}
return dst.split('->')
}
//iana codes are case-sensitive, technically
const titleCase = str => {
str = str[0].toUpperCase() + str.substr(1)
str = str.replace(/[/_-]([a-z])/gi, s => {
return s.toUpperCase()
})
str = str.replace(/_(of|es)_/i, (s) => s.toLowerCase())
str = str.replace(/\/gmt/i, '/GMT')
str = str.replace(/\/utc/i, '/UTC')
str = str.replace(/\/Dumontdurville$/i, '/DumontDUrville')
str = str.replace(/\/Mcmurdo$/i, '/McMurdo')
str = str.replace(/\/Port-au-prince$/i, '/Port-au-Prince')
if (str === 'Utc') {
str = 'UTC'
}
return str
}
//get metadata about this timezone
const timezone = s => {
const zones = s.timezones
let tz = s.tz
if (zones.hasOwnProperty(tz) === false) {
tz = findTz(s.tz, zones)
}
if (tz === null) {
if (s.silent === false) {
console.warn("Warn: could not find given or local timezone - '" + s.tz + "'")
}
return {
current: {
epochShift: 0
}
}
}
const found = zones[tz]
const result = {
name: titleCase(tz),
hasDst: Boolean(found.dst),
default_offset: found.offset,
//do north-hemisphere version as default (sorry!)
hemisphere: found.hem === 's' ? 'South' : 'North',
current: {}
}
if (result.hasDst) {
const arr = parseDst(found.dst)
result.change = {
start: arr[0],
back: arr[1]
}
}
//find the offsets for summer/winter times
//(these variable names are north-centric)
const summer = found.offset // (july)
let winter = summer // (january) assume it's the same for now
if (result.hasDst === true) {
if (result.hemisphere === 'North') {
winter = summer - 1
} else {
//southern hemisphere
winter = found.offset + 1
}
}
//find out which offset to use right now
//use 'summer' time july-time
if (result.hasDst === false) {
result.current.offset = summer
result.current.isDST = false
} else if (inSummerTime(s.epoch, result.change.start, result.change.back, summer, winter) === true) {
result.current.offset = summer
result.current.isDST = result.hemisphere === 'North' //dst 'on' in winter in north
} else {
//use 'winter' january-time
result.current.offset = winter
result.current.isDST = result.hemisphere === 'South' //dst 'on' in summer in south
}
return result
}
export default timezone

View File

@@ -0,0 +1,40 @@
const isOffset = /(-?[0-9]+)h(rs)?/i
const isNumber = /(-?[0-9]+)/
const utcOffset = /utc([\-+]?[0-9]+)/i
const gmtOffset = /gmt([\-+]?[0-9]+)/i
const toIana = function (num) {
num = Number(num)
if (num >= -13 && num <= 13) {
num = num * -1 //it's opposite!
num = (num > 0 ? '+' : '') + num //add plus sign
return 'etc/gmt' + num
}
return null
}
const parseOffset = function (tz) {
// '+5hrs'
let m = tz.match(isOffset)
if (m !== null) {
return toIana(m[1])
}
// 'utc+5'
m = tz.match(utcOffset)
if (m !== null) {
return toIana(m[1])
}
// 'GMT-5' (not opposite)
m = tz.match(gmtOffset)
if (m !== null) {
const num = Number(m[1]) * -1
return toIana(num)
}
// '+5'
m = tz.match(isNumber)
if (m !== null) {
return toIana(m[1])
}
return null
}
export default parseOffset

30
frontend/node_modules/spacetime/src/timezone/quick.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
/* eslint-disable no-console */
import isSummer from './summerTime.js'
// this method avoids having to do a full dst-calculation on every operation
// it reproduces some things in ./index.js, but speeds up spacetime considerably
const quickOffset = s => {
const zones = s.timezones
const obj = zones[s.tz]
if (obj === undefined) {
console.warn("Warning: couldn't find timezone " + s.tz)
return 0
}
if (obj.dst === undefined) {
return obj.offset
}
//get our two possible offsets
const jul = obj.offset
let dec = obj.offset + 1 // assume it's the same for now
if (obj.hem === 'n') {
dec = jul - 1
}
const split = obj.dst.split('->')
const inSummer = isSummer(s.epoch, split[0], split[1], jul, dec)
if (inSummer === true) {
return jul
}
return dec
}
export default quickOffset

View File

@@ -0,0 +1,19 @@
const MSEC_IN_HOUR = 60 * 60 * 1000
//convert our local date syntax a javascript UTC date
const toUtc = (dstChange, offset, year) => {
const [month, rest] = dstChange.split('/')
const [day, hour] = rest.split(':')
return Date.UTC(year, month - 1, day, hour) - (offset * MSEC_IN_HOUR)
}
// compare epoch with dst change events (in utc)
const inSummerTime = (epoch, start, end, summerOffset, winterOffset) => {
const year = new Date(epoch).getUTCFullYear()
const startUtc = toUtc(start, winterOffset, year)
const endUtc = toUtc(end, summerOffset, year)
// simple number comparison now
return epoch >= startUtc && epoch < endUtc
}
export default inSummerTime

38
frontend/node_modules/spacetime/src/whereIts.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import Spacetime from './spacetime.js'
// const timezones = require('../data');
const whereIts = (a, b) => {
let start = new Spacetime(null)
let end = new Spacetime(null)
start = start.time(a)
//if b is undefined, use as 'within one hour'
if (b) {
end = end.time(b)
} else {
end = start.add(59, 'minutes')
}
const startHour = start.hour()
const endHour = end.hour()
const tzs = Object.keys(start.timezones).filter((tz) => {
if (tz.indexOf('/') === -1) {
return false
}
const m = new Spacetime(null, tz)
const hour = m.hour()
//do 'calendar-compare' not real-time-compare
if (hour >= startHour && hour <= endHour) {
//test minutes too, if applicable
if (hour === startHour && m.minute() < start.minute()) {
return false
}
if (hour === endHour && m.minute() > end.minute()) {
return false
}
return true
}
return false
})
return tzs
}
export default whereIts

98
frontend/node_modules/spacetime/types/constraints.d.ts generated vendored Normal file
View File

@@ -0,0 +1,98 @@
export type TimeUnit =
| 'millisecond'
| 'second'
| 'minute'
| 'quarterHour'
| 'hour'
| 'day'
| 'week'
| 'month'
| 'quarter'
| 'season'
| 'year'
| 'decade'
| 'century'
| 'date'
| 'milliseconds' //plural forms
| 'seconds'
| 'minutes'
| 'quarterHours'
| 'hours'
| 'days'
| 'weeks'
| 'months'
| 'quarters'
| 'seasons'
| 'years'
| 'decades'
| 'centuries'
| 'dates'
export type Format =
| 'day'
| 'day-short'
| 'day-number'
| 'day-ordinal'
| 'day-pad'
| 'date'
| 'date-ordinal'
| 'date-pad'
| 'month'
| 'month-short'
| 'month-number'
| 'month-ordinal'
| 'month-pad'
| 'year'
| 'year-short'
| 'time'
| 'time-24'
| 'hour'
| 'hour-pad'
| 'hour-24'
| 'hour-24-pad'
| 'minute'
| 'minute-pad'
| 'second'
| 'second-pad'
| 'millisecond'
| 'ampm'
| 'quarter'
| 'season'
| 'era'
| 'timezone'
| 'offset'
| 'numeric'
| 'numeric-us'
| 'numeric-uk'
| 'mm/dd'
| 'iso'
| 'json'
| 'iso-short'
| 'iso-utc'
| 'iso-full'
| 'sql'
| 'nice'
| 'nice-year'
| 'nice-day'
| 'nice-full'
| string
export interface I18nOptions {
/** Alternatives to Monday, Tuesday..*/
days?: {
short: string[]
long: string[]
}
/** Alternatives to Jan, Feb..*/
months?: {
short: string[]
long: string[]
}
/** Alternatives to am, pm*/
ampm?: {
am: string
pm: string
}
/** Default dayname formatting */
useTitleCase?: boolean
}

View File

@@ -0,0 +1,94 @@
import type { Spacetime, ParsableDate, TimezoneSet } from './types.js'
export interface SpacetimeConstructorOptions {
/** javascript dates use millisecond-epochs, instead of second-epochs, like some other languages. This is a common bug, and by default spacetime warns if you set an epoch within January 1970. to disable set to true */
silent?: boolean
/** the day number, between 0-6, that the week starts on. (Sunday is 0) */
weekStart?: number
/** pass true to change parsing behaviour to dd/mm/yyyy. By default American interpretation will be used. */
dmy?: boolean
}
export interface SpacetimeConstructor {
/**
* @param epoch Timestamp in **milliseconds**. If you are getting a date in 1970, you are likely using seconds.
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(epoch: number, timezone?: string, options?: SpacetimeConstructorOptions): Spacetime
/**
* @param arr Date values in an array such as [yyyy, m, d].
*
* ```typescript
* let d = spacetime([2011, 1, 15]);
* d.format('nice-year'); // "Feb 15th, 2011"
* ```
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(arr: Array<number>, timezone?: string, options?: SpacetimeConstructorOptions): Spacetime
/**
* @param obj Date as a key-value object. ex {month:'june', year:2019}
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(
obj: { [unit: string]: string | number },
timezone?: string,
options?: SpacetimeConstructorOptions
): Spacetime
/**
* @param iso Date as an iso string. ex '2017-04-03T08:00:00'
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(iso: string, timezone?: string, options?: SpacetimeConstructorOptions): Spacetime
/**
* @param parsableDate a parsable date like object
* @param timezone Optional timezone. If omitted uses the browser timezone.
* @param options Options for silencing warnings.
*/
(
parsableDate?: ParsableDate | null,
timezone?: string,
options?: SpacetimeConstructorOptions
): Spacetime
}
export interface SpacetimeStatic extends SpacetimeConstructor {
/** set as the current time */
now: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as this morning */
today: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as tomorrow morning */
tomorrow: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as yesterday morning */
yesterday: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set epoch using seconds instead of milliseconds */
fromUnixSeconds: (seconds: number, timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** Extend Spacetime with a custom function/object. */
extend: (extension: { [key: string]: any } | {}) => SpacetimeStatic
/** get a list of current timezones and their offsets */
timezones: () => TimezoneSet
/** list timezones by their time */
whereIts: (a: string, b?: string) => string[]
/** set as earliest-possible date */
min: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
/** set as furthest-possible future date */
max: (timezone?: string, options?: SpacetimeConstructorOptions) => Spacetime
}

6
frontend/node_modules/spacetime/types/index.d.cts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
import type { SpacetimeStatic } from './constructors'
declare const spacetime: SpacetimeStatic
// We need to use a single default export here so everything lines up with the actual imported object from JS
export = spacetime

11
frontend/node_modules/spacetime/types/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import type { SpacetimeStatic } from './constructors.js'
declare const spacetime: SpacetimeStatic
// We need to use a single default export here so everything lines up with the actual imported object from JS
export default spacetime
export { SpacetimeConstructor, SpacetimeConstructorOptions, SpacetimeStatic } from './constructors.js'
export { Format, I18nOptions, TimeUnit } from './constraints.js'
export { Spacetime, Diff, ParsableDate, Progress, Since, TimezoneMeta, TimezoneSet } from './types.js'

364
frontend/node_modules/spacetime/types/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,364 @@
import type { TimeUnit, Format, I18nOptions } from './constraints.js'
/** a date/timezone object */
export interface Spacetime {
/**
* @deprecated use toNativeDate. This is an implementation detail that was not intended for external use
* @returns the date as a native date object
*/
d: Date
/** @returns epoch in milliseconds */
epoch: number
/** @returns whether warnings are enabled */
silent: boolean
/** @returns the timezone tz database name, eg, 'america/denver' */
tz: string
/** @returns the tz database nameset */
timezones: TimezoneSet
/** move to a new timezone, but at this same moment. Accepts an IANA code or abbreviation */
goto: (target: string | null) => Spacetime
/** @returns a copy of this object, with no references to the original */
clone: () => Spacetime
/**
* @deprecated use toNativeDate()
* @returns the native Date object at the same epoch
*/
toLocalDate(): Date
/** @returns the native Date object at the same epoch */
toNativeDate(): Date
/** @returns a bunch of meta-data about your current timezone */
timezone(): TimezoneMeta
/** swap the timezone, but keep the same date-time (if possible) */
timezone(tz: String): Spacetime
/** output nicely-formatted strings */
format: (format: Format) => string
/** output formatted string using unix formatting code (yyyy.MM.dd h:mm a) */
unixFmt: (format: string) => string
/** move to the first millisecond of the day, week, month, year, etc. */
startOf: (unit: TimeUnit) => Spacetime
/** move to the last millisecond of the day, week, month, year, etc. */
endOf: (unit: TimeUnit) => Spacetime
/** increment the time by a number and unit - like an hour, minute, day, or year */
add: (value: number, unit: TimeUnit) => Spacetime
/** decrease the time by a number and unit - like an hour, minute, day, or year */
subtract: (value: number, unit: TimeUnit) => Spacetime
/** go to the beginning of the next unit */
next: (unit: TimeUnit) => Spacetime
/** round to either current, or +1 of this unit */
nearest: (unit: TimeUnit) => Spacetime
/** round to either current, or +1 of this unit */
round: (unit: TimeUnit) => Spacetime
/** list all dates up to a certain time */
every: (unit: Spacetime | string | TimeUnit, end: Spacetime | string | TimeUnit, stepCount: number) => Spacetime[]
/** list all dates up to a certain time */
each: (unit: TimeUnit, end: Spacetime | string) => Spacetime[]
/** go to the beginning of the previous unit */
last: (unit: TimeUnit) => Spacetime
/** pass-in a spacetime object or date input and see if it takes-place after your spacetime date/time */
isAfter: (date: Spacetime | Date) => boolean
/** pass-in a spacetime object or date input and see if it takes-place before your spacetime date/time */
isBefore: (date: Spacetime | Date) => boolean
/** is this date on the exact same millisecond as another */
isEqual: (date: Spacetime | Date) => boolean
/** is this date between these start and end dates? */
isBetween: (start: Spacetime | Date, end: Spacetime | Date, isInclusive?: boolean) => boolean
/** detect if two date/times are the same day, week, or year, etc */
isSame: (
date: Spacetime | Date | TimeUnit,
unit: Spacetime | Date | TimeUnit,
tzSensitive?: boolean
) => boolean
/** given a date and a unit, count how many of them you'd need to make the dates equal */
diff(value: Spacetime | ParsableDate, unit: TimeUnit): number
/** given a date, count how many of various units to make the dates equal */
diff(value: Spacetime | ParsableDate): Diff
/** create the human-readable diff between the two dates */
since(value: Spacetime | ParsableDate): Since
/** create the human-readable diff between the two dates */
from(value: Spacetime | ParsableDate): Since
/** create the human-readable diff between now and the given date */
fromNow(value: Spacetime | ParsableDate): Since
/** change to a new date */
set(date: ParsableDate): Spacetime
/** does this time exist on the gregorian/javascript calendar? */
isValid: () => boolean
/** which decade is it? */
decade(): number
/** set the current decade */
decade(decade: string | number): Spacetime
/** which century is it? */
century(): number
/** set the current century */
century(century: string | number): Spacetime
/** which millenium is it? */
millenium(): number
/** set the current millenium */
millenium(millenium: string | number): Spacetime
/** which millennium is it? */
millennium(): number
/** set the current millennium */
millennium(millennium: string | number): Spacetime
/** pretty-print the date to the console, for nicer debugging */
log: () => Spacetime
/** pretty-print the full-date to the console, for nice debugging */
logYear: () => Spacetime
/** return all date units as a key-value map */
json(): object
/** set the date via JSON object */
json(obj: object): Spacetime
/** Between 0-1, how far the moment lands between the start and end of the day/week/month/year. */
progress: (unit?: string) => Progress
/** is the current year a leap year? */
leapYear: () => boolean
/** is daylight-savings-time activated right now, for this timezone? */
isDST: () => boolean
/** is daylight-savings-time activated right now, for this timezone? */
inDST: () => boolean
/** does this timezone ever use daylight-savings */
hasDST: () => boolean
/** the current, DST-aware time-difference from UTC, in hours */
offset: () => number
/** what hemisphere is it? */
hemisphere: () => string
/** checks if the current time is between 8am and 10pm */
isAwake: () => boolean
/** checks if the current time is between 10pm and 8am */
isAsleep: () => boolean
/** get the current number of milliseconds (0-999) */
millisecond(): number
/** set the current number of milliseconds (0-999) */
millisecond(value: number): Spacetime
/** get the current number of seconds (0-59) */
second(): number
/** set the current number of seconds (0-59) */
second(value: number, goForward?: boolean): Spacetime
/** get the current number of minutes (0-59) */
minute(): number
/** set the current number of minutes (0-59) */
minute(value: number, goForward?: boolean): Spacetime
/** get the current hour, in 24 time (0-23). */
hour(): number
/** set the current hour, in 24 time (0-23). also accepts/parses '3pm' */
hour(value: number | string, goForward?: boolean): Spacetime
/** get the current hour, in 12-hour format (0-11). */
hour12(): number
/** set the current hour, in 12-hour format (0-11). also accepts/parses '3pm' */
hour12(value: number | string, goForward?: boolean): Spacetime
/** get the date/time as ISO 8601*/
iso(): string
/** set the date/time/offset from a ISO 8601 string */
iso(iso: string): Spacetime
/** get the date/time as an extended ISO 8601 string (RFC 9557)*/
isoFull(): string
/** set the date/time/offset from an extended ISO 8601 string (RFC 9557)*/
isoFull(iso: string): Spacetime
/** get the day-number of the month (1- max31) */
date(): number
/** set the day-number of the month (1- max31) */
date(value: number, goForward?: boolean): Spacetime
/** get the zero-based month-number (0-11). */
month(): number
/** set the zero-based month-number (0-11). Also accepts 'June', or 'oct'. */
month(value: string | number, goForward?: boolean): Spacetime
/** get the 4-digit year as an integer */
year(): number
/** set the 4-digit year as an integer */
year(value: number): Spacetime
/** get a formatted, 12-hour time, like '11:30pm' */
time(): string
/** set a formatted, 12-hour time, like '11:30pm' */
time(value: string, goForward?: boolean): Spacetime
/** get the week-number of the year (1-52) */
week(): number
/** set the week-number of the year (1-52) */
week(value: number, goForward?: boolean): Spacetime
/** get the fiscal-quarter (1-4) */
quarter(): number
/** set the fiscal-quarter (1-4) */
quarter(value: number, goForward?: boolean): Spacetime
/** get the name of the season, spring/summer/fall/autumn/winter */
season(): string
/** set the name of the season, spring/summer/fall/autumn/winter */
season(value: string, goForward?: boolean): Spacetime
/** get the era, 'BC' or 'AD' */
era(): 'BC' | 'AD'
/** set the era, 'BC' or 'AD' (flips the year between positive and negative) */
era(value: 'BC' | 'AD' | 'bc' | 'ad'): Spacetime
/** get the hour + minute in decimal form, so '3:30am' is 3.5 */
hourFloat(): number
/** set the hour + minute in decimal form, so '3:30am' is 3.5 */
hourFloat(value: number, goForward?: boolean): Spacetime
/** get the day of the week as an integer, starting on sunday (day-0) */
day(): number
/** set the day of the week as an integer, starting on sunday (day-0). Also accepts names like 'wednesday', or 'thurs' */
day(value: number | string, goForward?: boolean): Spacetime
/** get the day of the week as lower-case string */
dayName(): string
/** set the day of the week */
dayName(value: string, goForward?: boolean): Spacetime
/** get the day as an integer 1-365 */
dayOfYear(): string
/** set the day of the year */
dayOfYear(value: number, goForward?: boolean): Spacetime
/** get whether the time is am or pm */
ampm(): string
/** set whether the time is am or pm */
ampm(value: string, goForward?: boolean): Spacetime
/** get number of seconds since Jan 1 1970 */
epochSeconds(): number | null
/** set the time, using seconds since Jan 1 1970 */
epochSeconds(value: number): Spacetime
/** get the general time-of-day, like 'afternoon' */
dayTime(): string
/** set the general time-of-day, like 'afternoon' */
dayTime(value: string, goForward?: boolean): Spacetime
/** get the current month as a string, like 'april' */
monthName(): string
/** set the current month as a string, like 'april' */
monthName(value: string, goForward?: boolean): Spacetime
/** the day number, between 0-6, that the week starts on. (Sunday is 0). Also accepts 'sunday' */
weekStart(value: number | string): Spacetime
/** returns the amount of days the current month has (December => 31, June => 30, ...) */
daysInMonth: () => number
/** format dates using non-english words */
i18n: (newWords: I18nOptions) => Spacetime
}
export interface TimezoneMeta {
change?: { start: string; back: string }
current: { offset: number; isDST: boolean }
default_offset: number
display: string
hasDst: boolean
hemisphere: string
name: string
}
export interface Progress {
/** Progress of value from 0-1 */
day: number
/** Progress of value from 0-1 */
hour: number
/** Progress of value from 0-1 */
minute: number
/** Progress of value from 0-1 */
month: number
/** Progress of value from 0-1 */
quarter: number
/** Progress of value from 0-1 */
quarterHour: number
/** Progress of value from 0-1 */
season: number
/** Progress of value from 0-1 */
week: number
/** Progress of value from 0-1 */
year: number
}
export interface Diff {
days: number
hours: number
milliseconds: number
minutes: number
months: number
seconds: number
weeks: number
years: number
quarters: number
}
export interface Since {
diff: Diff
rounded: string
qualified: string
precise: string
abbreviated: string[]
iso: string
direction: 'past' | 'present' | 'future'
}
/** set where the key is tz database name in lowercase, eg, 'america/denver' */
export interface TimezoneSet {
[key: string]: {
offset: number
hem: string
dst?: string
}
}
export type ParsableDate = Spacetime | Date | number | Array<number> | string

87
frontend/node_modules/spacetime/zonefile/_build.js generated vendored Normal file
View File

@@ -0,0 +1,87 @@
export default {
"9|s": "2/dili,2/jayapura",
"9|n": "2/chita,2/khandyga,2/pyongyang,2/seoul,2/tokyo,2/yakutsk,11/palau,japan,rok",
"9.5|s|04/05:03->10/04:02": "4/adelaide,4/broken_hill,4/south,4/yancowinna",
"9.5|s": "4/darwin,4/north",
"8|s|03/13:01->10/02:00": "12/casey",
"8|s": "2/kuala_lumpur,2/makassar,2/singapore,4/perth,2/ujung_pandang,4/west,singapore",
"8|n": "2/brunei,2/hong_kong,2/irkutsk,2/kuching,2/macau,2/manila,2/shanghai,2/taipei,2/ulaanbaatar,2/chongqing,2/chungking,2/harbin,2/macao,2/ulan_bator,2/choibalsan,hongkong,prc,roc",
"8.75|s": "4/eucla",
"7|s": "12/davis,2/jakarta,9/christmas",
"7|n": "2/bangkok,2/barnaul,2/hovd,2/krasnoyarsk,2/novokuznetsk,2/novosibirsk,2/phnom_penh,2/pontianak,2/ho_chi_minh,2/tomsk,2/vientiane,2/saigon",
"6|s": "12/vostok",
"6|n": "2/bishkek,2/dhaka,2/omsk,2/thimphu,2/urumqi,9/chagos,2/dacca,2/kashgar,2/thimbu",
"6.5|n": "2/yangon,9/cocos,2/rangoon",
"5|s": "12/mawson,9/kerguelen",
"5|n": "2/almaty,2/aqtau,2/aqtobe,2/ashgabat,2/atyrau,2/dushanbe,2/karachi,2/oral,2/qyzylorda,2/qostanay,2/samarkand,2/tashkent,2/yekaterinburg,9/maldives,2/ashkhabad",
"5.75|n": "2/kathmandu,2/katmandu",
"5.5|n": "2/kolkata,2/colombo,2/calcutta",
"4|s": "9/reunion",
"4|n": "2/baku,2/dubai,2/muscat,2/tbilisi,2/yerevan,8/astrakhan,8/samara,8/saratov,8/ulyanovsk,8/volgograd,9/mahe,9/mauritius,2/volgograd",
"4.5|n": "2/kabul",
"3|s": "12/syowa,9/antananarivo",
"3|n|04/24:00->10/29:24": "0/cairo,egypt",
"3|n|03/29:03->10/25:04": "2/famagusta,2/nicosia,8/athens,8/bucharest,8/chisinau,8/helsinki,8/kyiv,8/mariehamn,8/riga,8/sofia,8/tallinn,8/uzhgorod,8/vilnius,8/zaporozhye,8/nicosia,8/tiraspol,8/kiev,eet",
"3|n|03/29:00->10/24:24": "2/beirut",
"3|n|03/28:02->10/24:02": "2/gaza,2/hebron",
"3|n|03/27:02->10/25:02": "2/jerusalem,2/tel_aviv,israel",
"3|n": "0/addis_ababa,0/asmara,0/asmera,0/dar_es_salaam,0/djibouti,0/juba,0/kampala,0/mogadishu,0/nairobi,2/aden,2/amman,2/baghdad,2/bahrain,2/damascus,2/kuwait,2/qatar,2/riyadh,8/istanbul,8/kirov,8/minsk,8/moscow,8/simferopol,9/comoro,9/mayotte,2/istanbul,turkey,w-su",
"3.5|n": "2/tehran,iran",
"2|s|03/29:02->10/25:02": "12/troll",
"2|s": "0/gaborone,0/harare,0/johannesburg,0/lubumbashi,0/lusaka,0/maputo,0/maseru,0/mbabane",
"2|n|03/29:02->10/25:03": "0/ceuta,arctic/longyearbyen,8/amsterdam,8/andorra,8/belgrade,8/berlin,8/bratislava,8/brussels,8/budapest,8/busingen,8/copenhagen,8/gibraltar,8/ljubljana,8/luxembourg,8/madrid,8/malta,8/monaco,8/oslo,8/paris,8/podgorica,8/prague,8/rome,8/san_marino,8/sarajevo,8/skopje,8/stockholm,8/tirane,8/vaduz,8/vatican,8/vienna,8/warsaw,8/zagreb,8/zurich,3/jan_mayen,poland,cet,met",
"2|n": "0/blantyre,0/bujumbura,0/khartoum,0/kigali,0/tripoli,8/kaliningrad,libya",
"1|s": "0/brazzaville,0/kinshasa,0/luanda,0/windhoek",
"1|n|03/29:01->10/25:02": "3/canary,3/faroe,3/madeira,8/dublin,8/guernsey,8/isle_of_man,8/jersey,8/lisbon,8/london,3/faeroe,eire,8/belfast,gb-eire,gb,portugal,wet",
"1|n": "0/algiers,0/bangui,0/douala,0/lagos,0/libreville,0/malabo,0/ndjamena,0/niamey,0/porto-novo,0/tunis",
"14|n": "11/kiritimati",
"13|s": "11/apia,11/tongatapu",
"13|n": "11/enderbury,11/kanton,11/fakaofo",
"12|s|04/05:03->09/27:02": "12/mcmurdo,11/auckland,12/south_pole,nz",
"12|s": "11/fiji",
"12|n": "2/anadyr,2/kamchatka,2/srednekolymsk,11/funafuti,11/kwajalein,11/majuro,11/nauru,11/tarawa,11/wake,11/wallis,kwajalein",
"12.75|s|04/05:03->04/05:02": "11/chatham,nz-chat",
"11|s|04/05:03->10/04:02": "12/macquarie",
"11|s": "11/bougainville",
"11|n": "2/magadan,2/sakhalin,11/efate,11/guadalcanal,11/kosrae,11/noumea,11/pohnpei,11/ponape",
"11.5|n|04/05:03->10/04:02": "11/norfolk",
"10|s|04/05:03->10/04:02": "4/currie,4/hobart,4/melbourne,4/sydney,4/act,4/canberra,4/nsw,4/tasmania,4/victoria",
"10|s": "12/dumontdurville,4/brisbane,4/lindeman,11/port_moresby,4/queensland",
"10|n": "2/ust-nera,2/vladivostok,11/guam,11/saipan,11/chuuk,11/truk,11/yap",
"10.5|s|04/05:01->10/04:02": "4/lord_howe,4/lhi",
"0|s|02/15:03->03/22:02": "0/casablanca,0/el_aaiun",
"0|n|03/29:00->10/25:01": "3/azores",
"0|n|03/29:00->10/24:24": "1/scoresbysund",
"0|n": "0/abidjan,0/accra,0/bamako,0/banjul,0/bissau,0/conakry,0/dakar,0/freetown,0/lome,0/monrovia,0/nouakchott,0/ouagadougou,0/sao_tome,1/danmarkshavn,3/reykjavik,3/st_helena,13/gmt,13/utc,0/timbuktu,13/greenwich,13/uct,13/universal,13/zulu,gmt-0,gmt+0,gmt0,greenwich,iceland,uct,universal,utc,zulu,13/unknown,factory",
"-9|n|03/08:02->11/01:02": "1/adak,1/atka,us/aleutian",
"-9|n": "11/gambier",
"-9.5|n": "11/marquesas",
"-8|n|03/08:02->11/01:02": "1/anchorage,1/juneau,1/metlakatla,1/nome,1/sitka,1/yakutat,us/alaska",
"-8|n": "11/pitcairn",
"-7|n|03/08:02->11/01:03": "1/vancouver,6/pacific",
"-7|n|03/08:02->11/01:02": "1/los_angeles,1/santa_isabel,1/tijuana,1/ensenada,10/bajanorte,us/pacific-new,us/pacific",
"-7|n": "1/creston,1/dawson,1/dawson_creek,1/fort_nelson,1/hermosillo,1/mazatlan,1/phoenix,1/whitehorse,6/yukon,10/bajasur,us/arizona,mst",
"-6|s|04/04:22->09/05:22": "11/easter,7/easterisland",
"-6|n|04/07:02->10/27:02": "1/merida",
"-6|n|03/08:02->11/01:02": "1/boise,1/cambridge_bay,1/denver,1/edmonton,1/inuvik,1/north_dakota,1/ojinaga,1/ciudad_juarez,1/yellowknife,1/shiprock,6/mountain,navajo,us/mountain",
"-6|n": "1/bahia_banderas,1/belize,1/chihuahua,1/costa_rica,1/el_salvador,1/guatemala,1/managua,1/mexico_city,1/monterrey,1/regina,1/swift_current,1/tegucigalpa,11/galapagos,6/east-saskatchewan,6/saskatchewan,10/general",
"-5|s": "1/lima,1/rio_branco,1/porto_acre,5/acre",
"-5|n|03/08:02->11/01:02": "1/chicago,1/matamoros,1/menominee,1/rainy_river,1/rankin_inlet,1/resolute,1/winnipeg,1/indiana/knox,1/indiana/tell_city,1/north_dakota/beulah,1/north_dakota/center,1/north_dakota/new_salem,1/knox_in,6/central,us/central,us/indiana-starke",
"-5|n": "1/bogota,1/cancun,1/cayman,1/coral_harbour,1/eirunepe,1/guayaquil,1/jamaica,1/panama,1/atikokan,jamaica,est",
"-4|s|04/04:24->09/06:00": "1/santiago,7/continental",
"-4|s|03/22:24->10/05:00": "1/asuncion",
"-4|s": "1/campo_grande,1/cuiaba,1/la_paz,1/manaus,5/west",
"-4|n|03/08:02->11/01:02": "1/detroit,1/grand_turk,1/indiana,1/indianapolis,1/iqaluit,1/kentucky,1/louisville,1/montreal,1/nassau,1/new_york,1/nipigon,1/pangnirtung,1/port-au-prince,1/thunder_bay,1/toronto,1/indiana/marengo,1/indiana/petersburg,1/indiana/vevay,1/indiana/vincennes,1/indiana/winamac,1/kentucky/monticello,1/fort_wayne,1/indiana/indianapolis,1/kentucky/louisville,6/eastern,us/east-indiana,us/eastern,us/michigan",
"-4|n|03/08:00->11/01:01": "1/havana,cuba",
"-4|n": "1/anguilla,1/antigua,1/aruba,1/barbados,1/blanc-sablon,1/boa_vista,1/caracas,1/curacao,1/dominica,1/grenada,1/guadeloupe,1/guyana,1/kralendijk,1/lower_princes,1/marigot,1/martinique,1/montserrat,1/port_of_spain,1/porto_velho,1/puerto_rico,1/santo_domingo,1/st_barthelemy,1/st_kitts,1/st_lucia,1/st_thomas,1/st_vincent,1/tortola,1/virgin",
"-3|s": "1/argentina,1/buenos_aires,1/catamarca,1/cordoba,1/coyhaique,1/fortaleza,1/jujuy,1/mendoza,1/montevideo,1/punta_arenas,1/sao_paulo,12/palmer,12/rothera,3/stanley,1/argentina/la_rioja,1/argentina/rio_gallegos,1/argentina/salta,1/argentina/san_juan,1/argentina/san_luis,1/argentina/tucuman,1/argentina/ushuaia,1/argentina/comodrivadavia,1/argentina/buenos_aires,1/argentina/catamarca,1/argentina/cordoba,1/argentina/jujuy,1/argentina/mendoza,1/argentina/rosario,1/rosario,5/east",
"-3|n|03/08:02->11/01:02": "1/glace_bay,1/goose_bay,1/halifax,1/moncton,1/thule,3/bermuda,6/atlantic",
"-3|n": "1/araguaina,1/bahia,1/belem,1/cayenne,1/maceio,1/paramaribo,1/recife,1/santarem",
"-2|n|03/08:02->11/01:02": "1/miquelon",
"-2|n": "1/noronha,3/south_georgia,5/denoronha",
"-2.5|n|03/08:02->11/01:02": "1/st_johns,6/newfoundland",
"-1|n|03/29:00->10/24:24": "1/nuuk,1/godthab",
"-1|n": "3/cape_verde",
"-11|n": "11/midway,11/niue,11/pago_pago,11/samoa,us/samoa",
"-10|n": "11/honolulu,11/johnston,11/rarotonga,11/tahiti,us/hawaii,hst"
}

17
frontend/node_modules/spacetime/zonefile/_prefixes.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
//prefixes for iana names..
export default [
'africa',
'america',
'asia',
'atlantic',
'australia',
'brazil',
'canada',
'chile',
'europe',
'indian',
'mexico',
'pacific',
'antarctica',
'etc'
]

159
frontend/node_modules/spacetime/zonefile/aliases.js generated vendored Normal file
View File

@@ -0,0 +1,159 @@
// tzs that dont exist in zoneinfo anymore
// cldraliases from timezonenames
// https://github.com/mj1856/timezonenames
// link-name : target
export default {
'africa/asmera': 'africa/nairobi',
'africa/timbuktu': 'africa/abidjan',
'america/atka': 'america/adak',
'america/coral_harbour': 'america/atikokan',
'pacific/enderbury': 'pacific/kanton',
'asia/volgograd': 'europe/volgograd',
// argentina
'america/argentina/comodrivadavia': 'america/catamarca',
'america/argentina/buenos_aires': 'america/buenos_aires',
'america/argentina/catamarca': 'america/catamarca',
'america/argentina/cordoba': 'america/cordoba',
'america/argentina/jujuy': 'america/jujuy',
'america/argentina/mendoza': 'america/mendoza',
'america/argentina/rosario': 'america/cordoba',
'america/ensenada': 'america/tijuana',
'america/fort_wayne': 'america/indianapolis',
'america/godthab': 'america/nuuk',
'america/indiana': 'america/indianapolis',
'america/indiana/indianapolis': 'america/indianapolis',
'america/kentucky': 'america/louisville',
'america/kentucky/louisville': 'america/louisville',
'america/north_dakota': 'america/boise',
'america/knox_in': 'america/indiana/knox',
'america/montreal': 'america/toronto',
'america/porto_acre': 'america/rio_branco',
'america/rosario': 'america/cordoba',
'america/santa_isabel': 'america/tijuana',
'america/shiprock': 'america/denver',
'america/virgin': 'america/port_of_spain',
'antarctica/south_pole': 'pacific/auckland',
'asia/ashkhabad': 'asia/ashgabat',
'asia/calcutta': 'asia/kolkata',
'asia/chongqing': 'asia/shanghai',
'asia/chungking': 'asia/shanghai',
'asia/dacca': 'asia/dhaka',
'asia/harbin': 'asia/shanghai',
'asia/istanbul': 'europe/istanbul',
'asia/kashgar': 'asia/urumqi',
'asia/katmandu': 'asia/kathmandu',
'asia/macao': 'asia/macau',
'asia/rangoon': 'asia/yangon',
'asia/saigon': 'asia/ho_chi_minh',
'asia/tel_aviv': 'asia/jerusalem',
'asia/thimbu': 'asia/thimphu',
'asia/ujung_pandang': 'asia/makassar',
'asia/ulan_bator': 'asia/ulaanbaatar',
'asia/choibalsan': 'asia/ulaanbaatar',
'atlantic/faeroe': 'atlantic/faroe',
'atlantic/jan_mayen': 'europe/oslo',
'australia/act': 'australia/sydney',
'australia/canberra': 'australia/sydney',
'australia/currie': 'australia/hobart',
'australia/lhi': 'australia/lord_howe',
'australia/north': 'australia/darwin',
'australia/nsw': 'australia/sydney',
'australia/queensland': 'australia/brisbane',
'australia/south': 'australia/adelaide',
'australia/tasmania': 'australia/hobart',
'australia/victoria': 'australia/melbourne',
'australia/west': 'australia/perth',
'australia/yancowinna': 'australia/broken_hill',
'brazil/acre': 'america/rio_branco',
'brazil/denoronha': 'america/noronha',
'brazil/east': 'america/sao_paulo',
'brazil/west': 'america/manaus',
'canada/atlantic': 'america/halifax',
'canada/central': 'america/winnipeg',
'canada/east-saskatchewan': 'america/regina',
'canada/eastern': 'america/toronto',
'canada/mountain': 'america/edmonton',
'canada/newfoundland': 'america/st_johns',
'canada/pacific': 'america/vancouver',
'canada/saskatchewan': 'america/regina',
'canada/yukon': 'america/whitehorse',
'chile/continental': 'america/santiago',
'chile/easterisland': 'pacific/easter',
cuba: 'america/havana',
egypt: 'africa/cairo',
eire: 'europe/dublin',
'etc/greenwich': 'etc/gmt',
'etc/uct': 'etc/utc',
'etc/universal': 'etc/utc',
'etc/zulu': 'etc/utc',
'europe/belfast': 'europe/london',
'europe/nicosia': 'asia/nicosia',
'europe/tiraspol': 'europe/chisinau',
'gb-eire': 'europe/london',
gb: 'europe/london',
'gmt-0': 'etc/gmt',
'gmt+0': 'etc/gmt',
gmt0: 'etc/gmt',
greenwich: 'etc/gmt',
hongkong: 'asia/hong_kong',
iceland: 'atlantic/reykjavik',
iran: 'asia/tehran',
israel: 'asia/jerusalem',
jamaica: 'america/jamaica',
japan: 'asia/tokyo',
kwajalein: 'pacific/kwajalein',
libya: 'africa/tripoli',
'mexico/bajanorte': 'america/tijuana',
'mexico/bajasur': 'america/mazatlan',
'mexico/general': 'america/mexico_city',
navajo: 'america/denver',
'nz-chat': 'pacific/chatham',
nz: 'pacific/auckland',
'pacific/johnston': 'pacific/honolulu',
'pacific/ponape': 'pacific/pohnpei',
'pacific/samoa': 'pacific/pago_pago',
'pacific/truk': 'pacific/chuuk',
'pacific/yap': 'pacific/chuuk',
poland: 'europe/warsaw',
portugal: 'europe/lisbon',
prc: 'asia/shanghai',
roc: 'asia/taipei',
rok: 'asia/seoul',
singapore: 'asia/singapore',
turkey: 'europe/istanbul',
uct: 'etc/utc',
universal: 'etc/utc',
'us/alaska': 'america/anchorage',
'us/aleutian': 'america/adak',
'us/arizona': 'america/phoenix',
'us/central': 'america/chicago',
'us/east-indiana': 'america/indianapolis',
'us/eastern': 'america/new_york',
'us/hawaii': 'pacific/honolulu',
'us/indiana-starke': 'america/indiana/knox',
'us/michigan': 'america/detroit',
'us/mountain': 'america/denver',
'us/pacific-new': 'america/los_angeles',
'us/pacific': 'america/los_angeles',
'us/samoa': 'pacific/pago_pago',
utc: 'etc/utc',
'w-su': 'europe/moscow',
zulu: 'etc/utc',
'etc/unknown': 'etc/utc',
'europe/kiev': 'europe/kyiv',
//rogue acronym results found in results of
// Intl.supportedValuesOf('timeZone')
cet: 'europe/paris',
eet: 'europe/sofia',
est: 'america/cancun',
factory: 'etc/utc',
hst: 'pacific/honolulu',
met: 'europe/paris',
mst: 'america/phoenix',
wet: 'europe/lisbon'
}

1900
frontend/node_modules/spacetime/zonefile/iana.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

47
frontend/node_modules/spacetime/zonefile/pack.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
//turn our timezone data into a small-as-possible string
import { writeFileSync } from 'fs'
import iana from './iana.js'
import aliases from './aliases.js'
import prefixes from './_prefixes.js'
const all = {}
// add aliases in
Object.keys(aliases).forEach((k) => {
const found = iana[aliases[k]]
if (!found) {
console.log('missing', aliases[k])
}
iana[k] = Object.assign({}, found)
})
//pack iana data into a [o|h] object
Object.keys(iana).forEach((k) => {
const o = iana[k]
let key = o.offset + '|' + o.hem
if (o.dst) {
key += '|' + o.dst
}
all[key] = all[key] || []
const name = k.replace(/(.*?)\//, (a, prefix) => {
const index = prefixes.indexOf(prefix)
if (index !== -1) {
return index + '/'
}
return a
})
all[key].push(name)
})
//add-in informal abbreviations
// all = addHemisphere(all, informal.south, 's')
// all = addHemisphere(all, informal.north, 'n')
let keys = Object.keys(all)
keys = keys.sort((a, b) => (a < b ? 1 : -1))
const result = {}
keys.forEach((k) => {
result[k] = all[k].join(',')
})
// console.log(result)
writeFileSync('./zonefile/_build.js', 'export default ' + JSON.stringify(result, null, 2))

47
frontend/node_modules/spacetime/zonefile/unpack.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import data from './_build.js'
import prefixes from './_prefixes.js'
const all = {}
Object.keys(data).forEach((k) => {
const split = k.split('|')
const obj = {
offset: Number(split[0]),
hem: split[1]
}
if (split[2]) {
obj.dst = split[2]
}
const names = data[k].split(',')
names.forEach((str) => {
str = str.replace(/(^[0-9]+)\//, (before, num) => {
num = Number(num)
return prefixes[num] + '/'
})
all[str] = obj
})
})
all.utc = {
offset: 0,
hem: 'n' //default to northern hemisphere - (sorry!)
}
//add etc/gmt+n
for (let i = -14; i <= 14; i += 0.5) {
let num = i
if (num > 0) {
num = '+' + num
}
let name = 'etc/gmt' + num
all[name] = {
offset: i * -1, //they're negative!
hem: 'n' //(sorry)
}
name = 'utc/gmt' + num //this one too, why not.
all[name] = {
offset: i * -1,
hem: 'n'
}
}
export default all