Code Monkey home page Code Monkey logo

spacetime's Introduction

Isn't it weird how we can do math in our head, but not date math?

- how many days until the end of the year?
-what time was it, 11 hours ago?
-is it lunchtime in france?

and worse - there is no real date calculator.

people end up asking google, and going to weird websites.

that's bad.

spacetime is a date-calculator,

It's very small, and very handy.
let s = spacetime.now()

s.diff(s.endOf('year'), 'days')
// 292

s.minus(11, 'hours').time()
// 6:50am

s = s.now('Europe/Paris')
s.isAfter(s.time('11:00am'))
// true ๐Ÿฅ

  • calculate time in remote timezones
  • support daylight savings, leap years, and hemispheres
  • Moment-like API (but immutable)
  • Orient time by quarter, season, month, week..
  • Zero Dependencies - (no Intl API)
  • weighs about 40kb.
  • has a cool plugin thing.

<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>

npm install spacetime

const spacetime = require('spacetime')
let d = spacetime.now('Europe/Paris')
d.dayName()
//'Wednesday'
d.isAsleep()
//true

typescript / babel / deno:

import spacetime from 'spacetime'
let d = spacetime.now()
d.format('nice')
//'Apr 1st, 4:32pm'

Demo ย  ย  โ€ข ย  ย  Full API

plugins:

Date Inputs:

we can parse all the normal stuff, and some fancy stuff:

//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
// NOTE: this returns the date in the local browsers timezone
jsDate = spacetimeDate.toNativeDate()

for fancier natural-language inputs, use compromise-dates.

Get & Set dates:

you can whip things around, but stay intuitive

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 add a week, 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.

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.

Comparisons:

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.

Timezones:

the best way to describe a timezone is an IANA code:

// 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

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:

//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.

spacetime().time('4:30pm').goto('Europe/Paris').goto(null).time()
// 4:30pm

Date Formatting:

it's a pretty-sensible process to create nice-looking dates:

// 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'

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

Daylight-savings gotchas

We've written in detail about how spacetime handles Daylight-savings changes here

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.

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:

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.

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:

// 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:

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():

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:

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:

spacetime('12/01/2018', null, { dmy: true }) //jan 12th

this format is more common in britain, and south america.

Custom languages:

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: ' a. 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',
    secondPlural: 'second',
    minute: 'minute',
    minutePlural: 'minutes',
    hour: 'hour',
    hourPlural: 'hours',
    day: 'day',
    dayPlural: 'seconds',
    month: 'month',
    monthPlural: 'months',
    year: 'year',
    yearPlural: '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

let s = spacetime.now()
s = s.weekStart('sunday')

s = s.startOf('week')
s.dayName()
//sunday

s = s.endOf('week')
s.dayName()
//saturday

See also:

thank you to the amazing timeanddate.com

Apache 2.0

spacetime's People

Contributors

9parsonsb avatar ai avatar alexmanzo-fundrise avatar brianleroux avatar bsvetlik avatar coatesap avatar darshandixit05 avatar davidurco avatar domamato avatar e1himself avatar graham42 avatar hunteva avatar itscindella avatar jecraig avatar joe-pritchard avatar joonassirenpaf avatar marccuesta99 avatar matthewjamesadam avatar mbbzrc avatar mitsunee avatar nfinished avatar nlap avatar pbarbiero avatar ryanblock avatar samtgarson avatar scottarnold avatar serraniel avatar shaungrady avatar spencermountain avatar vbv-shm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spacetime's Issues

add week over dst-change

tricky double-day bug:

///BUG:
let d = spacetime('2019-11-04T00:00:00.000')
let s = d
for (let i = 0; i < 7; i += 1) {
  console.log(s.format('date'))
  s = s.add(1, 'day')
}

d = d.add(1, 'week')
console.log('---')
for (let i = 0; i < 7; i += 1) {
  console.log(d.format('date'))
  d = d.add(1, 'day')
}
/*
4
5
6
7
8
9
10
---
10
11
12
13
14
15
16
*/

Possible a timezone issue, .d property wrong value

Give the following snipet:

const spacetime = require('spacetime')
const date = spacetime('2019-02-16T23:14:34+01:00')
// date.d -> 2019-02-16T21:14:34.157Z !incorrect
// date.iso() -> 2019-02-16T23:14:34.157+01:00 correct
const otherDate = new Date(Date.parse(date.iso()))
// otherDate -> 2019-02-16T22:14:34.157Z correct

It seems that the .d property has some issues with (probably) the timezone? In any case, it's not a representation of the parsed date.

Strange bug for add week

Yesterday straight after midnight (I am in timezone "Europe/Berlin") I started to see a strange bug when trying to add one week to certain dates. Examples 2018-10-22 and a few following days. This morning I don't have the problem, but when I jump to timezone "America/Adak" I managed to reproduce the bug.

Here you could see how adding a week to 21 of Oktober works fine, but on the day after only 6 days gets added: https://runkit.com/toreskog/5baea71a80fd230012a7930a

set quarter fail-case

bug (from mexico city tz)

 let s = spacetime([2017, 5, 25]);
 s.quarter('q2')
 console.log(s.format('nice'))

should be April 1, but is March 31

Spacetime appears to ignore timezone when parsing ISO times

const timestamp = '2017-04-03T08:00:00-0700'
const s = spacetime(timestamp)
const date = new Date(timestamp)

s.timezone().name
// "Europe/London"

s.hour()
// 8 

date.getUTCHours()
// 15 

Unless I'm missing something in how spacetime is supposed to be used, I can't see a way of telling the library that a) the date was in a different timezone to me or b) to somehow localize the datetime I gave it.

It appears here that you match for a timezone but then don't do anything with it (it would be arr[5]).

I'm happy to put in a PR but I wanted to check I wasn't misunderstanding what this library is supposed to do.

support ISO space-seperator

Hi, I tested the following code๏ผš

console.log(spacetime('2018-02-02T22:00:00'))
console.log(spacetime('2018-02-02 22:00:00'))

The first line, I get:

{tz: "Asia/Shanghai", valid: true, epoch: 1517580000262}

The second line, I get:

Warning: couldn't parse date-string: '2018-02-02 22:00:00'
u @ spacetime.js?be0a:4
u @ spacetime.js?be0a:5
i @ spacetime.js?be0a:4
submitDiary @ Index.vue?2753:49
boundFn @ vue.esm.js?efeb:190
click @ Index.vue?1a5d:176
invoker @ vue.esm.js?efeb:2004
fn._withTask.fn._withTask @ vue.esm.js?efeb:1802
Index.vue?2753:49 u {tz: "Asia/Shanghai", valid: false, epoch: null}

Actually, for date strings, I use spaces as separators more often than ever. Do you think you can add this feature? Thank you.

"since" seems output unexpected differences

Not sure this is a bug or misunderstand the API.
"since" call seems to output some questionable result, please refer the screenshots below.

image

couldn't understand why it's '3 days 11 hours ago', since 'diff' with days only output -1

Support isBetween API?

How about supporting isBetween api for checking if a date is in the range

var now = spacetime().now()
var start = spacetime('July 2, 2017 5:01:00')
var end = spacetime('July 2, 2018 5:01:00')

// return true or false
now.isBetween(start, end)

Unexpected epoch return value without dst

Hi, I'm playing with your package and I think that I found a problem with the returned epoch value. Here is the code:

var spacetime = require('spacetime');

var s1 = spacetime([2017, 9, 4, 10, 20, 0, 0], 'Europe/Madrid');
console.log("[spacetime] iso date: " + s1.format('iso') + "  epoch: " + s1.epoch);
console.log("[spacetime] tz name: " + s1.timezone().name);
console.log("[spacetime] offset: " + s1.timezone().current.offset);
console.log("[spacetime] isDst: " + s1.timezone().current.isDst);

// There is a DST change on 29-10-2017 at 03:00:00

var s2 = spacetime([2017, 9, 30, 10, 20, 0, 0], 'Europe/Madrid');
console.log("[spacetime] iso date: " + s2.format('iso') + "  epoch: " + s2.epoch);
console.log("[spacetime] tz name: " + s2.timezone().name);
console.log("[spacetime] offset: " + s2.timezone().current.offset);
console.log("[spacetime] isDst: " + s2.timezone().current.isDst);

And the output is:

[spacetime] iso date: 2017-10-04T10:20:00:000Z  epoch: 1507105200000
[spacetime] tz name: Europe/Madrid
[spacetime] offset: 120
[spacetime] isDst: true
[spacetime] iso date: 2017-10-30T10:20:00:000Z  epoch: 1509358800000
[spacetime] tz name: Europe/Madrid
[spacetime] offset: 60
[spacetime] isDst: false

If I use https://www.epochconverter.com/ with the first epoch (1507105200000) I see what I expect, the GMT value is: "GMT: Wednesday, October 4, 2017 8:20:00 AM" because there is a 120 offset.

But If I set the second epoch (1509358800000) the GMT value is unexpected: "GMT: Monday, October 30, 2017 10:20:00 AM". What I expect should be GMT: Monday, October 30, 2017 09:20:00 AM because there is a 60 offset.

There is a bug or I'm missing something?
Thanks

[Feature] Allow manual i18n

It would be nice to have basic support for translating the days and months.

While it would also be nice to include a bunch of locales ready to go, its not necessary if a method is exposed to update the strings.

Is this something you would consider, and would you humor a pull request to add this behavior if I get time to do so?

implicit 0's behaviour-change

spacetime('2019-01-25T20:00:00+01:00').isBefore('2019-01-25T20:00:00+01:00') returns true, but clearly is the same date. Prob is, when milliseconds are not specified, the parser doesn't assume 0, but a random (prob taken from current date) value.

Implement `fromNow` method

Greetings, I was curious if implementing Moment's fromNow feature is in the roadmap? It seems like it wouldn't be too tough to do by leveraging diff.

Just thinking through the rough logic:

  • Diff on years; if years >= 1, ${years} year(s) ago, else...
  • Diff on months; if months >= 1, ${months} month(s) ago else...
  • Et cetera.

Pluralization of the time unit would be handled, of course, and the logic Moment uses would be easy to duplicate.

If this is something you'd like to support, and the rough approach above sounds like the right path to you, I could do a bit of work and open a PR.

time-sensitive bucharest bug

set computer time to 7:30pm EST

console.log(spacetime('March 1st 2015', 'Europe/Bucharest').format('nice'))
//Mar 31st, 2:43am

only march overflows. error begins at 7:20pm and ends at 8:20pm.

bucharest has a dst switch at 03/25:03, may be related

Unexpected am/pm results with object input

The ampm parameter of the object date input seems to default to pm when it's passed null or an empty string without a timezone. All the other params that I've tested seem to fallback to .now() values, but 'ampm' always defaults to pm, which seems a bit off, especially when null or a blank string are passed (I would expect am).

Here's what I tested:

spacetime({month:'12', day:'25', hour:'6', minute:'24', ampm:null}).format('nice')
/* and */
spacetime({month:'12', day:'25', hour:'6', minute:'24', ampm:''}).format('nice')

/* return "Dec 25th, 6:24pm" */

This is really obvious if you try to pass a 24h time:

spacetime({month:'12', day:'25', hour:'15', minute:'24', ampm:null}).format('nice')
/* and */
spacetime({month:'12', day:'25', hour:'15', minute:'24', ampm:''}).format('nice')

/* return "Dec 26th, 3:24am" */

If you add a timezone, or remove the ampm param altogether, it works as expected (defaults to am):

spacetime({month:'12', day:'25', hour:'15', minute:'24', ampm:null}, 'America/New_York').format('nice')
/* and */
spacetime({month:'12', day:'25', hour:'15', minute:'24'}).format('nice')

/* return "Dec 25th, 3:24pm" */

ES Modules + .mjs

Hi there!! This is really neat! I was wondering if any of us at webpack could help ship this code over using ES Module Syntax?

Can include motivations if needed! ๐Ÿ‘จโ€๐Ÿ”ฌ๐Ÿ”ฅ

Feature Request - allow passing of arbitrary tzdata files.

There's this excellent family of IANA Timezone data files published on NPM now:

You can depend on everything by using the root package:
https://www.npmjs.com/package/tzdata

Or, you can pull out just the areas that you want, like:
https://www.npmjs.com/package/tzdata-asia

It would be incredibly useful if spacetime were to expose an API for initialising with arbitrary tzdata so that we could manage both the accuracy and scope (and therefore bundle size) of our applications when using spacetime.

Nice wee package, enjoying it so far!

abstract-over DST change in .diff()

Sympton

> from = spacetime("2019-02-05 00:00:00")
SpaceTime { epoch: 1549278000878, tz: 'pacific/auckland', silent: true }
> from = spacetime("2019-02-05 00:00:00.0")
SpaceTime { epoch: 1549278000000, tz: 'pacific/auckland', silent: true }
> to = from.clone().minus(20, 'years')
SpaceTime { epoch: 918126000000, tz: 'pacific/auckland', silent: true }
> to.diff(from)
{ milliseconds: 631152000000,
  seconds: 631152000,
  minutes: 10519200,
  hours: 175320,
  years: 20,
  months: 240,
  weeks: 1047,
  days: 7305 }

Weeks should be 1043 instead of 1047

Cause

Week diff use climb way to adds weeks one by one until it reaches the target, the underlying adds function collects ms,sec,hour before the addition and then feeds them to the 'walk(s, want)' function to walk around and get precise match, but it could potentially step back for 23 hours rather than 1 hour while cross from non-dst to dst dates as shown in above, which cause the outer diff loop went more round and produce more week difference.

Root cause

ok, just found the root of this:

> a = spacetime('2018-03-29 00:00:0.0')
SpaceTime { epoch: 1522234800000, tz: 'pacific/auckland', silent: true }
> b = a.clone().add(1, 'week')
SpaceTime { epoch: 1522756800000, tz: 'pacific/auckland', silent: true }
> b.since(a)
{ diff:
   { years: 0, months: 0, days: 6, hours: 24, minutes: 0, seconds: 0 },
  rounded: '7 days ago',
  qualified: 'almost 7 days ago',
  precise: '6 days, 24 hours ago' }
> a.format('{mdy} {time-24}')
'03/29/2018 0:00'
> b.format('{mdy} {time-24}')
'04/04/2018 0:00'

it should be '04/04/2018 23:00' because dst instead of '0:00', the 'add' function actually step back for 23 hour.

Fix

  • A 'dst compensate' step before it went for a 'walk'.
    - or just normal ms division instead of climb for 'week' diff

please @spencermountain, would like to hear your advise

definite need to fix the add & walk issue, should be come up a fix shortly

time-sensitive leap-year issue

//from Jan 8th 10:30am EST
let s = spacetime('June 30, 2017 20:01:00', 'Australia/Brisbane');
console.log(s.format('nice'))
//spacetime warning: missed setting day
//Jun 1st, 8:01pm

spacetime is not defined

Hi,
After a couple of weeks of pausing, I just pulled a project I was working on that uses spacetime.
However, I keep getting "spacetime is not defined" regardless of using
<script src="https://unpkg.com/spacetime"></script>,
https://unpkg.com/[email protected]/builds/spacetime.min.js
or if src is a local file copied from that same URL
Any pointers? :/
Thanks a lot!

PST to PDT is off by one day

Hello all.

I have a method that converts UTC to a dynamic local time but testing using America/Los_Angeles the library seems to be off by one day when PST goes over to PDT (winter to summer time)

According to timeanddate.com/time/zone/usa/los-angeles the time change should occur 2018-03-11 02:00:00 but this seems to happen 2018-03-12 02:00:00 local time.

Code

// From config config.TIME.FORMAT.RAW_DATE_UNIX_LOCAL
RAW_DATE_UNIX_LOCAL: 'YYYY-MM-dd HH:mm:ss'

/**
 * Converts from UTC to naive time - timezone aware
 * @param {string} date
 */
function _dateUTCToLocal (date) {
    // Display as local time
    const s =
        spacetime(date)
        .goto(store.getters.getUser.facility.timezone)

    console.log('BEFORE', date, 'AFTER', s.format(config.TIME.FORMAT.RAW_DATE_UNIX_LOCAL))

    // Display as local time
    return s.format(config.TIME.FORMAT.RAW_DATE_UNIX_LOCAL)
}

console.log output

BEFORE 2018-03-12T07:00:00+00:00 AFTER 2018-03-11 23:00:00
BEFORE 2018-03-12T08:00:00+00:00 AFTER 2018-03-12 00:00:00
BEFORE 2018-03-12T09:00:00+00:00 AFTER 2018-03-12 01:00:00
BEFORE 2018-03-12T10:00:00+00:00 AFTER 2018-03-12 03:00:00
BEFORE 2018-03-12T11:00:00+00:00 AFTER 2018-03-12 04:00:00
BEFORE 2018-03-12T12:00:00+00:00 AFTER 2018-03-12 05:00:00

Thanks in advance. Love the project!

Typings file

from recurrent googling, seems the popular way to expose the api now is a .d.ts typings file, and pointing to it from package.json. I'm easy regarding any alternative formats.

moment tests it this way, which seems doable for us.
-thoughts @brianleroux ?

Fractional Timezone Support

It looks like Spacetime has a bit of trouble with fractional timezones, and gets a bit confused with reading in timezones that are ahead / behind GMT. Example:

// Create a starting place (noon today GMT)
s = spacetime('2018-08-28T12:00:00Z')

// Setup some timezones to look at
let timezones = [
  {
    timezone: 'America/Toronto',  // -4h
  },
  {
    timezone: 'Asia/Muscat', // +4h
  },
  {
    timezone: 'Asia/Kathmandu', // +5h 45m
  },
  {
    timezone: 'Asia/Calcutta', // +5h 30m
  }
]

timezones = timezones.map(tz => {
  // Create a version of the above time in this timezone
  thisSpacetime = s.clone().goto(tz.timezone)
  offset = thisSpacetime.timezone().current.offset,
  nice =  thisSpacetime.format('nice')
  iso = thisSpacetime.format('iso')
  
  // Create a (hopefully identical) version of the above timezone
  interpreted = spacetime(iso)
  interpretedOffset = interpreted.epoch ? interpreted.timezone().current.offset : '',
  interpretedIso = interpreted.format('iso')
  interpretedNice = interpreted.format('nice')

  return {
    ...tz,
    offset,
    nice,
    iso,
    interpretedOffset,
    interpretedIso,
    interpretedNice
  }
})

console.table(timezones)

Outputs the following:

image

Issues:

  1. The generated ISO timestamps appear to have the timezone backwards - for Toronto, I would expect a timestamp of "2018-08-28T08:00:00.758-04:00", not "2018-08-28T08:00:00.758+04:00"
  2. ST seems to interpret all positive number timezones as negative numbers (see the interpretted timezone of Asia / Muscat differing from the original offset)
  3. The generated ISO dates for Asia/Kathmandu and Asia/Calcutta is not a proper ISO timestamp, and as such can't be accepted as input to spacetime

I'm willing to chalk some of this up to my inexperience with the lib / confusion with timezones.

[Feature] Unix formatting

There are many cases where allowing unix style formats would let this library be used in many more places than it can be today. I myself have many cases where the list of included formats do not expose nearly enough flexibility or control to get the exact format needed.

Would you consider adding a new method (or extending the current one) such as .formatUnix() or something? It could also possibly be a secondary optional package to include which will extend spacetime with the unix formatting capability.

Background
This (and the lack of i18n support) is preventing me from adopting this library over moment which I desperately want to move on from for many reasons. This looks to be the first viable competitor because of the excellent timezone support (and all of my use-cases don't need the historical accuracy!)

Exposing this functionality (even as an optional module) I am sure would be useful for many others as well in the same situation as I am. There are many cases where legacy processes or database operations require an exact, specific format.

On stplot()

311.pdf
Task4_6.311.RData.zip

Greetings!

I have an stidf (trajectory) element and I am trying to display it with an stplot() function, as described below. However:

Firstly, the cuts where I want the colors to change are not "understood" by the stplot().
Secondly, I am not sure how to show the coordinates on the graph.
Thirdly, the code shows an error message on the image: "error using packet, could not find function 'stidf'".
Finally, the "name.attr" argument does not respond.

Thank you for your attention! Best regards.


#Variable
fileMonth3<-311

load(paste0("Task4_6.",fileMonth3,".RData"));stidf_model<-stidf_SIMAR

#layout

m <- map2SpatialLines(map(database="world",xlim = c(-5,10),
ylim = c(32,46), plot =F))

proj4string(m) <- "+proj=longlat +datum=WGS84 +ellps=WGS84"

layout1 <- list(list("sp.lines", m, col = "gray"), list("stidf",stidf_model, first = FALSE, cex = 0.5))

#plot and save map

pdf(paste0("fileMonth3,".pdf"))

#plotting rHs

stplot(stidf_model[1:length(stidf_model@sp),1:nrow(stidf_model@time),2],
sp.layout=layout1,number=1,name.attr="var1.pred",
at=seq(-1,1,by=0.5))
dev.off()

Possible to make timezone data tree-shakeable?

My impression is that its the timezone data that makes up most of the size of a library like this.

As a follow up to #37: Would it perhaps be possible to make the timezone data tree-shakeable? So that only the data for the time zones that one are actively referencing gets included?

If you're unfamiliar with the concept, then here's some more reading: https://webpack.js.org/guides/tree-shaking/ It do require ESM

Error when trying to change time zone to Tomsk, Volgograd and +13

When trying to change time zone to:

  • Asia/Tomsk
  • Asia/Volgograd
  • Coordinated Universal time +13

using .goto() it returns an error: Cannot read property 'dst' of undefined.

In the pictures below trying to load spacetime.how website after changing the computer's time zone to these 3 time zones and getting that error. Checked with all time zones provided with Windows 10 settings and only those three returned this error.

timezone-universal-plus13
timezone-volgo
tomsk-error 1

'diff-big' test fail on specific time

Pretty sure it's related to #90 feel need to document it here since it breaks tests.

image

As can seen from above, there was 20 days difference when running it later. (10 days diff if only minus 10 year)

Glad to fix on this one by the way.

.format() refactor

create .unixFormat and ensure output equals moment.format's spec

move unix formatting out of format, that way we avoid crazy cruft of special characters and stuff.

maybe .format() should support .format('it is [time] o'clock') or something like that.

Open to proposals!

Season incorrect

The season in the southern hemisphere is incorrectly being reported as being the same as the northern hemisphere.

Example:
It's currently winter in the southern hemisphere, but the library reports it as summer.

Set time bug

Having a problem setting the time using immutable. Trying to set the time to 08:00, but for some reason it seems to be set to the current hour.

I reproduced the bug with runkit: https://runkit.com/toreskog/5ba7999d0612d500122fbb97

const spacetime = require("spacetime/immutable")

const day = spacetime('2018-09-23').time('06:00')
console.log(day.format('iso')) // --> "2018-09-23T15:00:00.000+02:00"

list timezones?

loving the lightweight timezone library, but i don't see a way to list all timezones.
you've got this whole data module, can we get a function to expose it?

spacetime.zones() perhaps?

Bug with southern hemisphere and DST

It seems that the DST "change" property it's not rightly handled in the southern hemisphere.

For example, if you set as date 2017-10-09 12:00 UTC and go to America/Sao_Paulo timezone, hour() method should return 09:00 because (ref):

  • UTC standard offset is -3;
  • UTC DST offset is -2;
  • DST starts on october 15th

Coherently, if you change date to 2017-10-16 it should return as 10:00.

At this line the dst.change is constantly set to -60, but in the case above it should be +60.

Indeed, the timezone().offsets property returns {base: -240, dst: -180} instead of {base: -180, dst: -120}

Same happens with America/Campo_Grande and America/Cuiaba.

I can't understand if this pattern (inverse of current dst.change) could be applied to every timezone in the southern hemisphere.

Take a look to this repl

Timezone abbreviations

Is there a way to get abbreviation or full timezone name like "EST" or "Eastern Standard Time", for now I can only get "America/New_York".
ex:

const now = spacetime.now() 
now.goto('America_New_York')
now.timezone().format('zz')  
/*
returns 'America/New_York', is there a way for it to return 'EDT'/'EST' 
or 'Eastern Daylight Time'/'Eastern Standard Time'?
*/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.