BJ Homer Profile picture
Mar 4 12 tweets 3 min read
Javascript and Swift apparently disagree about when January 1, 1 AD was. (Both numbers in milliseconds-since-1970)

JS:
-62135596800000

Swift:
-62135769600000

These two numbers are exactly 48 hours apart. Can anyone explain what’s going on here?
Okay, I’ve found *part* of the problem. When the Gregorian Calendar was first instituted, then needed to implement a 10-day jump to put the vernal equinox back in the right place. This meant that the day after October 4, 1582 was October 15, 1582.
Swift understands this. JS does not.

-12219296400 is the timestamp 1 hour before the beginning of October 15, 1582 (UTC). That means it should be October 4, 23:00 hours, because of the skipped days.

JS gives back October 14, 1582. A day that did not exist.
Okay, so we’ve found a difference. But… that’s a difference of TEN days. It still doesn’t explain why there are only 48 hours between the two “January 1, 1 AD”s.
Side note: Day One’s calendar is smart, and knows about these 10 missing days!
More exploration!

JS is off by:
9 days on Jan 1, 1500. (JS says Jan 10)
8 days on Jan 1, 1400
7 days on Jan 1, 1300
7 days on Jan 1, 1200
6 days on Jan 1, 1100
5 days on Jan 1, 1000
4 days on Jan 1, 900
4 days on Jan 1, 800
3 days on Jan 1, 700
2 days on Jan 1, 600
(…)
JS timestamps are off from the Gregorian calendar by:
1 day on Jan 1, 500
1 day on Jan 1, 400
0 days on Jan 1, 300 (!)
-1 day on Jan 1, 200
-2 days on Jan 1, 100

Now remember, there’s no year 0. The year before 1AD is 1BC.

-2 days on Jan 1, 1 AD
-2 days on Jan 1, 1 BC
Okay, so I think we’ve found the culprit. Leap years!

The Gregorian calendar specifies that leap years happen on every year divisible by 4, except not those divisible by 100 unless they are also divisible by 400.

The Julian calendar just did them every 4 years.
If I’m understanding this right, Javascript is using a *hybrid* calendar for its dates; using the Gregorian calendar for dates on or after October 15, 1582, and a Julian calendar for dates before that time.

Swift is using the Gregorian Calendar consistently throughout.
So, if you’re asking “how many seconds before Jan 1, 1970 was Jan 1, 1 AD”, you need to first answer “which calendar are you referencing?”
Turns out, this was in fact exactly backwards! Swift is the one using a hybrid calendar. That’s useful in general for presenting dates to a user, but probably less useful for constructing ISO8601 date strings. In this particular case, I think JS has it right!

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with BJ Homer

BJ Homer Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @bjhomer

Oct 25, 2021
You may pick one superpower:

1. You can fly… but only to/from the grocery store.
2. You can turn invisible… but only on weekends.
3. You can turn into any animal… but only when no one can see you.

Which would you choose, and what would you do with it?

(Details in 🧵)
Flying:
• Speed of a typical passenger jet
• You can carry things, but they don’t fly on their own
• A “Grocery Store” is whatever you can convince yourself to believe is a grocery store
• You won’t get cold while flying, but you still need oxygen.
Invisibility:
• You can turn anything within 1 foot of your body invisible. This covers clothes, etc, but only the portion near your body.
• “Weekends” are Saturday 12AM through Monday 12AM in local time zone
• Invisibility is selective. e.g. you can hide just your hand
Read 5 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(