12

Is there any specification for the syntax of dates passed to git? For example, what dates are accepted by the "--before" option to "git rev-list"?

Assuming there is no such specification, is there any way to get git to transform a date into a canonical form, so that one can check that a given date string is being interpreted as one expects? (Update: I've written a script to do this, which is available here.)

Informational note: date parsing seems to be implemented in the file date.c, in the root of git's repository. The "entry point" seems to be a function called approxidate_careful.

  • Note: Git 2.2+ (Nov 2014) now has a `--date=iso-strict`: see [my answer below](http://stackoverflow.com/a/26961655/6309) – VonC Nov 16 '14 at 20:25
  • Note parsing of date in order to decide between `dd/mm/yy` or `mm/dd/yy` has changed with Git .2.2.2 (January 2015). See [my answer below](http://stackoverflow.com/a/28256582/6309). – VonC Jan 31 '15 at 21:14

6 Answers6

6

It’s not explicitly noted anywhere as far as I can tell, but it seems to accept all formats that it can output, as described in the documentation for the --date option:

--date=(relative|local|default|iso|rfc|short|raw)

Only takes effect for dates shown in human-readable format, such as when using --pretty. log.date config variable sets a default value for log command’s --date option.

--date=relative shows dates relative to the current time, e.g. "2 hours ago".

--date=local shows timestamps in user’s local timezone.

--date=iso (or --date=iso8601) shows timestamps in ISO 8601 format.

--date=rfc (or --date=rfc2822) shows timestamps in RFC 2822 format, often found in E-mail messages.

--date=short shows only date but not time, in YYYY-MM-DD format.

--date=raw shows the date in the internal raw git format %s %z format.

--date=default shows timestamps in the original timezone (either committer’s or author’s).

Ry-
  • 209,133
  • 54
  • 439
  • 449
  • thanks! the git docs and man pages imply this only affects dates that are _output_, but in practice it also affects input date parsing as well. – ryan Feb 19 '19 at 22:22
4

As you already found out git is usually using approxidate for parsing all kind of times. This allows you to write all kind of natural to crazy ways to specify a time.

This allows you to write things like “six minutes ago” or “last Tuesday” or even "tea time" and approxidate usually understands what you mean. I am not aware of any explicit documentation other than the source you already found.

A nice blog entry on that topic is http://www.alexpeattie.com/blog/working-with-dates-in-git/

michas
  • 24,015
  • 14
  • 69
  • 112
2

The real code is at https://github.com/git/git/blob/master/date.c#L717 and enumerates the available formats such as iso8601, rfc2822 and various short, local, raw, and default formats.

Philip Oakley
  • 12,527
  • 9
  • 46
  • 67
2

Sadly, Git isn't consistent about what date and time formats it accepts. The internal, canonical format is a combination of the Unix timestamp (ie seconds since midnight 1 January 1970) and the timezone offset.

For specifying dates, that's somewhat hard to read. I'd use Git's interpretation of ISO 8601 for a format that's relatively easy to read and will always be unambiguous. Depending on the command you're using, you can often get this with --date=iso as minitech noted. It'll look something like 2012-12-26 23:17:23 +0000.

(The --date=rfc version is similarly unambiguous in that it will only be interpreted the same way, but that includes the weekday. I personally object to having that around, since it allows you to specify dates that look valid but where the day doesn't match the date, such as Sun, 26 Dec 2012 01:02:03 +0000 [That's today, a Wednesday].)

For the formats that are, I believe, accepted everywhere, run git help commit-tree; that man page includes the following (I've slightly reformatted):

Date formats

The GIT_AUTHOR_DATE, GIT_COMMITTER_DATE environment variables support the following date formats:

  • Git internal format: It is <unix timestamp> <timezone offset>, where <unix timestamp> is the number of seconds since the UNIX emoch. <timezone offset> is a positive or negative offset from UTC. For example CET (which is two hours ahead UTC) is +0200.

  • RFC 2822: The standard email format as described by RFC 2822, for example Thu, 07 Apr 2005 22:13:13 +0200.

  • ISO 8601: Time and date specified by the ISO 8601 standard, for example 2005-04-07T22:13:13. The parser accepts a space instead of the T character as well.

    Note: In addition, the date part is accepted in the following formats: YYYY.MM.DD, MM/DD/YYYY and DD.MM.YYYY.

Some places use "approxidate" and as such are less fussy, as michas noted. If you fancy digging into this, the code is in Git's date.c (that link via the Working With Dates in Git link michas posted). For example, the below is from git help revisions:

Specifying revisions

  • <refname>@{<date>}, e.g. master@{yesterday}, HEAD@{5 minutes ago}: A ref followed the suffix @ with a date specification enclosed in a brace pair (e.g. {yesterday}, {1 month 2 weeks 3 days 1 hour 1 second ago} or `{1979-02-26 18:30:00}) specifies the value of the ref at a prior point in time. …
Community
  • 1
  • 1
me_and
  • 14,530
  • 7
  • 61
  • 96
1

Note that the "date=iso" format isn't exactly ISO 8601.
See commit "466fb67" from Beat Bolli (bbolli), for Git 2.2.0 (November 2014)

pretty: provide a strict ISO 8601 date format

Git's "ISO" date format does not really conform to the ISO 8601 standard due to small differences, and it cannot be parsed by ISO 8601-only parsers, e.g. those of XML toolchains.

The output from "--date=iso" deviates from ISO 8601 in these ways:

  • a space instead of the T date/time delimiter
  • a space between time and time zone
  • no colon between hours and minutes of the time zone

Add a strict ISO 8601 date format for displaying committer and author dates.
Use the '%aI' and '%cI' format specifiers and add '--date=iso-strict' or '--date=iso8601-strict' date format names.

See this thread for discussion.

VonC
  • 1,129,465
  • 480
  • 4,036
  • 4,755
0

Git 2.2.2 (January 2015) brings a small improvement when trying to decide between dd/mm/yy or mm/dd/yy.

See commit d372395 written by Jeff King (peff)

approxidate: allow ISO-like dates far in the future

When we are parsing approxidate strings and we find three numbers separate by one of ":/-.", we guess that it may be a date.
We feed the numbers to match_multi_number, which checks whether it makes sense as a date in various orderings (e.g., dd/mm/yy or mm/dd/yy, etc).

One of the checks we do is to see whether it is a date more than 10 days in the future. This was added in 38035cf (date parsing: be friendlier to our European friends., 2006-04-05, Git 1.3.0), and lets us guess that if it is currently April 2014, then "10/03/2014" is probably March 10th, not October 3rd.

This has a downside, though; if you want to be overly generous with your "--until" date specification, we may wrongly parse "2014-12-01" as "2014-01-12" (because the latter is an in-the-past date).
If the year is a future year (i.e., both are future dates), it gets even weirder. Due to the vagaries of approxidate, months after the current date (no matter the year) get flipped, but ones before do not.

This patch drops the "in the future" check for dates of this form, letting us treat them always as yyyy-mm-dd, even if they are in the future.
This does not affect the normal dd/mm/yyyy versus mm/dd/yyyy lookup, because this code path only kicks in when the first number is greater than 70 (i.e., it must be a year, and cannot be either a date or a month).

The one possible casualty is that "yyyy-dd-mm" is less likely to be chosen over "yyyy-mm-dd". That's probably OK, though because:

  1. The difference happens only when the date is in the future. Already we prefer yyyy-mm-dd for dates in the past.
  2. It's unclear whether anybody even uses yyyy-dd-mm regularly. It does not appear in lists of common date formats in Wikipedia.
  3. Even if (2) is wrong, it is better to prefer ISO-like dates, as that is consistent with what we use elsewhere in git.
VonC
  • 1,129,465
  • 480
  • 4,036
  • 4,755