16
  • TimeZone = CEST
  • date (GNU coreutils) 8.32
date -d "115 years ago"
Di 11. Aug 13:37:54 CET 1908
date -d "116 years ago"
date: invalid date ‘116 years ago’

Questions

  1. Is it possible to go back more than 115 years into the Past or 5879565 years into the Future?
  2. Why is this happening and throwing an error and where are these odd numbers coming from?
  3. Why does date -d "200 years ago 14 Mar " suddenly work then?
5
  • 5
    Can you include the date command's implementation and version please? For example, I see different behavior between date (GNU coreutils) 8.32 versus date (GNU coreutils) 8.28 Commented Aug 11, 2023 at 14:58
  • 3
    I wonder if the last issue is something to do with the IANA timezone database. Which city do you have your timezone set to? Commented Aug 11, 2023 at 16:43
  • 3
    I guess no time machine computers will want to run Unix... Commented Aug 14, 2023 at 6:06
  • I suppose the future date problem might either be due to the relative difference or the absolute result. If the latter, can you pin down the exact date that becomes invalid, e.g. date -d '11 Aug 5881588?
    – mwfearnley
    Commented Aug 18, 2023 at 9:08
  • @mwfearnley oh wow... as soon as I type in an more exact date it suddenly works. Such a weird thing, I really want to understand what is happening here^^
    – Bog
    Commented Aug 18, 2023 at 9:13

4 Answers 4

20

There are lots of almost-compatible ways of counting time and date.

The 'traditional' unix-time counts seconds since 1970 (a.k.a 'the epoch'). This has a huge problem in 32-bit representations, where it will run into integer overflow on Tuesday Jan 19 2038 (date -d "@$((0x7fffffff))").

A more 'modern' way is to count nanoseconds in a 64-bit counter.

The GNU coreutils 'date' delegates the date parsing to parse-datetime2.y, which is 2500 lines of bison code. The behaviour also depends on the environment. For example, using coreutils 8.32 I get different behaviour under Cygwin and Ubuntu, even though they're both compiled from the same sources. I also have a coreutils 8.22 running on a 64bit CentOS7, where it accepts dates from "20000000000 years ago" up until "20000000000 years"

In summary - it depends on your implementation of date.

Edited to add:

Philip Couling is onto something. Timezones are a mess to handle correctly.

Also, read Falsehoods programmers believe about time. Time might seem like a simple topic - but to handle it correctly is a bitch.

5
  • 3
    Are you referring to the Y2.038K issue? :)
    – doneal24
    Commented Aug 11, 2023 at 16:16
  • Check your TZ or other timezone settings; they matter for me. Commented Aug 12, 2023 at 2:12
  • 3
    The relationship between Unix time and UTC is ... complicated. See unix.stackexchange.com/q/283164/88378 Also see ucolick.org/~sla/leapsecs/epochtime.html and A brief history of time scales
    – PM 2Ring
    Commented Aug 14, 2023 at 6:45
  • Interesting. But I still don't understand where these numbers come from... I mean 115 and 5879565 are pretty odd numbers. There must be an explanation for that
    – Bog
    Commented Aug 16, 2023 at 13:15
  • Read the answer by Philip Couling. It looks like it's all down to timezone handling. (At least that covers the case of '115 years ago'.)
    – Popup
    Commented Aug 16, 2023 at 15:06
13

I strongly suspect the minimum limit 115 years ago (1908) here is caused by your timezone. But since you've not mentioned which time zone you are in I can't confirm it for sure.

Most computer systems are either set to UTC or otherwise a named geographic time zone, usually referencing a city like Europe/London. The geographic time zones account for the governments changing a place's time zone and require database of time zones for specific locations from specific date / time. This allows date/time to work across daylight savings changes and most acts of political stupidity.

So the most likely thing is that the time zone your are in only has recorded time zone offsets back to around 1908. On the other hand UTC calculations will go back indefinitely because the timezone database uses UTC (and UT [GMT] before 1960) as the reference time.

The concept of time zones is really surprisingly new with the first synchronisation occurring in 1840. Any time zone arithmetic before that would be messy guesswork and likely involve an adjustment for continental drift.


The future calculations of 5879565 years is most likely systemic, and related to Unix time (the number of seconds since 01 jan 1970 GMT not accounting for UTC leap seconds).

But care should also be take believing future calculations. You don't know what the timezone for a locale will be 100 years from now. And the code certainly didn't account for the sizable drift relative to Greenwich over 5.8 million years.

4
  • 1
    Why it seems in those older versions of GNU date/gnulib/glibc (like GNU date 8.32 on Ubuntu 22.04) , the limits seem to be related to the usage of tz files (as in when $TZ is Europe/Berlin or :Europe/Berlin vs TZ=CET-1...), it doesn't seem to be related to one timezone in particular as it happens for all of them. It works fine with GNU date 9.1 on Debian testing. Commented Aug 13, 2023 at 10:48
  • 2
    (and on that Debian testing system TZ=Europe/London date -d '@-6857654325' returns a 1752-09-09 date even though there never was such a date in London as they switched from Julian to Gregorian calender around that time Commented Aug 13, 2023 at 10:52
  • 1
    @StéphaneChazelas could you list which time zones you tried. I'll need to verify when I'm on front of my laptop. Correct me if I'm wrong, I didn't think IANA TZ database included Julian dates and the respective calendar cutover for various locales are included in IANA TZ database. Europe/London isn't a great example to test on since daylight savings didn't come in until 1900s and London has otherwise observed GMT (the basis of UTC) since... London began using sundials? Not sure. The observatory was founded in 1675. Commented Aug 13, 2023 at 14:58
  • 2
    Right. for f (/usr/share/zoneinfo*/*/*(.:t2)) TZ=$f date -d '116 years ago' >& /dev/null || echo $f on Ubuntu 22.04 (and in zsh) returns quite a few (including all the ones In Europe and US I had tested) but not all of them. On Debian testing, for f (/usr/share/zoneinfo*/*/*(.:t2)) TZ=$f date -d '20000 years ago' >& /dev/null || echo $f doesn't fail for any. Commented Aug 13, 2023 at 15:06
6

That really depends on the implementation you are using:

In the version I have, there are no such limits:

$ date -d "120 years ago"
Wed 12 Aug 14:20:26 UTC 1903

$ date -d "5000 years ago"
Tue 12 Aug 14:21:26 UTC -2977

(of course, with so early dates the proleptic calendar being used must be taken with a grain of salt)

$ date -d "+9879566 years"
Sat 12 Aug 14:24:17 UTC 9881589

$ date -d "+1000000000 years"
Sat 12 Aug 14:23:39 UTC 1000002023

It lets me go up and down to more than 2 million years:

$ date -d "+2147483524 years"
Tue 12 Aug 14:29:19 UTC 2147485547

$ date -d "+2147483525 years"
date: invalid date '+2147483525 years'

(124 years less than 2³¹ = 2147483648)

$ date -d "2147483772 years ago"
date: invalid date '2147483772 years ago'

$ date -d "2147483771 years ago"
Thu 12 Aug 14:32:23 UTC -2147481748

(123 years less than 2³¹ = 2147483648)

Which suggests it is internally using a 32bit signed value on a struct tm's tm_year (starting in 1900) when initially calculating the number of years to add or substract.

3
  • Are you sure implementation is the difference. Your tests are all in UTC which requires no timezone translation. When not in UTC the most common thing is to use geographic timezone. Any implementation claiming to know the time in Europe/London 2147483771 years ago is clearly broken. Commented Aug 13, 2023 at 9:20
  • 1
    @PhilipCouling I used UTC to post a timezone-agnostic answer. Works the same in London time: TZ=Europe/London date -d "2147483771 years ago" Fri 13 Aug 22:30:16 LMT -2147481748. LMT stands for Local mean time, since it's before any data stored in the Olson db - or in human annals; which can be a pain, since you would usually only need to go back an integral number of days, but it may drift you some minutes due to the difference of the city to the meridian.
    – Ángel
    Commented Aug 13, 2023 at 21:32
  • You missed my point. In any case, please could you list which version you tested to help future readers. FYI Europe/London cannot possibly drift from the meridian barring some cataclysmic geological event. Commented Aug 14, 2023 at 10:05
4

Using date --version = 8.32:-

date -d "116 years ago" gives date: invalid date ‘116 years ago’

but forcing it to display in UTC date -ud "116 years ago" gives Tue 13 Aug 12:13:25 UTC 1907

Indeed:- date -ud "20240000 years ago" yields Sun 13 Aug 12:15:55 UTC -20237977

3
  • 1
    This answer seems to be related to the time zone issue pointed out by Philip Couling, but could benefit from more explanation.
    – jpa
    Commented Aug 13, 2023 at 16:39
  • 2
    Answerer's profile tells UK. So indeed on a Debian 11 system running date 8.32, this can be reproduced with TZ=Europe/London date -d "116 years ago".
    – A.B
    Commented Aug 14, 2023 at 9:07
  • 1
    Addition to your answer: Thanks to @mwfearnley I found out by accident, that it also works if you type in an more exact date. For example: date -d "200 years ago 14 Mar " :)
    – Bog
    Commented Aug 18, 2023 at 9:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .