2009-08-31 10:30:16 +08:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='test date parsing and printing'
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
# arbitrary reference time: 2009-08-30 19:20:00
|
|
|
|
TEST_DATE_NOW=1251660000; export TEST_DATE_NOW
|
|
|
|
|
2016-06-21 05:10:29 +08:00
|
|
|
check_relative() {
|
2009-08-31 10:30:16 +08:00
|
|
|
t=$(($TEST_DATE_NOW - $1))
|
|
|
|
echo "$t -> $2" >expect
|
|
|
|
test_expect_${3:-success} "relative date ($2)" "
|
2018-03-24 15:44:36 +08:00
|
|
|
test-tool date relative $t >actual &&
|
2012-08-27 13:36:49 +08:00
|
|
|
test_i18ncmp expect actual
|
2009-08-31 10:30:16 +08:00
|
|
|
"
|
|
|
|
}
|
|
|
|
|
2016-06-21 05:10:29 +08:00
|
|
|
check_relative 5 '5 seconds ago'
|
|
|
|
check_relative 300 '5 minutes ago'
|
|
|
|
check_relative 18000 '5 hours ago'
|
|
|
|
check_relative 432000 '5 days ago'
|
|
|
|
check_relative 1728000 '3 weeks ago'
|
|
|
|
check_relative 13000000 '5 months ago'
|
|
|
|
check_relative 37500000 '1 year, 2 months ago'
|
|
|
|
check_relative 55188000 '1 year, 9 months ago'
|
|
|
|
check_relative 630000000 '20 years ago'
|
|
|
|
check_relative 31449600 '12 months ago'
|
|
|
|
check_relative 62985600 '2 years ago'
|
2009-08-31 10:30:16 +08:00
|
|
|
|
2016-06-21 05:11:59 +08:00
|
|
|
check_show () {
|
|
|
|
format=$1
|
|
|
|
time=$2
|
|
|
|
expect=$3
|
2017-06-15 21:51:22 +08:00
|
|
|
prereqs=$4
|
|
|
|
zone=$5
|
|
|
|
test_expect_success $prereqs "show date ($format:$time)" '
|
2016-06-21 05:11:59 +08:00
|
|
|
echo "$time -> $expect" >expect &&
|
2018-03-24 15:44:36 +08:00
|
|
|
TZ=${zone:-$TZ} test-tool date show:"$format" "$time" >actual &&
|
2016-06-21 05:11:59 +08:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
}
|
|
|
|
|
|
|
|
# arbitrary but sensible time for examples
|
|
|
|
TIME='1466000000 +0200'
|
|
|
|
check_show iso8601 "$TIME" '2016-06-15 16:13:20 +0200'
|
|
|
|
check_show iso8601-strict "$TIME" '2016-06-15T16:13:20+02:00'
|
|
|
|
check_show rfc2822 "$TIME" 'Wed, 15 Jun 2016 16:13:20 +0200'
|
|
|
|
check_show short "$TIME" '2016-06-15'
|
|
|
|
check_show default "$TIME" 'Wed Jun 15 16:13:20 2016 +0200'
|
|
|
|
check_show raw "$TIME" '1466000000 +0200'
|
2016-07-23 03:51:49 +08:00
|
|
|
check_show unix "$TIME" '1466000000'
|
2016-06-21 05:11:59 +08:00
|
|
|
check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000'
|
date: document and test "raw-local" mode
The "raw" format shows a Unix epoch timestamp, but with a
timezone tacked on. The timestamp is not _in_ that zone, but
it is extra information about the time (by default, the zone
the author was in).
The documentation claims that "raw-local" does not work. It
does, but the end result is rather subtle. Let's describe it
in better detail, and test to make sure it works (namely,
the epoch time doesn't change, but the zone does).
While we are rewording the documentation in this area, let's
not use the phrase "does not work" for the remaining option,
"--date=relative". It's vague; do we accept it or not? We do
accept it, but it has no effect (which is a reasonable
outcome). We should also refer to the option not as
"--relative" (which is the historical synonym, and does not
take "-local" at all), but as "--date=relative".
Helped-by: Jakub Narębski <jnareb@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-27 21:44:41 +08:00
|
|
|
check_show raw-local "$TIME" '1466000000 +0000'
|
2016-07-23 03:51:49 +08:00
|
|
|
check_show unix-local "$TIME" '1466000000'
|
2016-06-21 05:11:59 +08:00
|
|
|
|
2017-06-15 20:29:53 +08:00
|
|
|
check_show 'format:%z' "$TIME" '+0200'
|
|
|
|
check_show 'format-local:%z' "$TIME" '+0000'
|
|
|
|
check_show 'format:%Z' "$TIME" ''
|
date: use localtime() for "-local" time formats
When we convert seconds-since-epochs timestamps into a
broken-down "struct tm", we do so by adjusting the timestamp
according to the known offset and then using gmtime() to
break down the result. This means that the resulting struct
"knows" that it's in GMT, even though the time it represents
is adjusted for a different zone. The fields where it stores
this data are not portably accessible, so we have no way to
override them to tell them the real zone info.
For the most part, this works. Our date-formatting routines
don't pay attention to these inaccessible fields, and use
the same tz info we provided for adjustment. The one
exception is when we call strftime(), whose %Z format
reveals this hidden timezone data.
We solved that by always showing the empty string for %Z.
This is allowed by POSIX, but not very helpful to the user.
We can't make this work in the general case, as there's no
portable function for setting an arbitrary timezone (and
anyway, we don't have the zone name for the author zones,
only their offsets).
But for the special case of the "-local" formats, we can
just skip the adjustment and use localtime() instead of
gmtime(). This makes --date=format-local:%Z work correctly,
showing the local timezone instead of an empty string.
The new test checks the result for "UTC", our default
test-lib value for $TZ. Using something like EST5 might be
more interesting, but the actual zone string is
system-dependent (for instance, on my system it expands to
just EST). Hopefully "UTC" is vanilla enough that every
system treats it the same.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-15 21:52:17 +08:00
|
|
|
check_show 'format-local:%Z' "$TIME" 'UTC'
|
2017-06-15 20:29:53 +08:00
|
|
|
check_show 'format:%%z' "$TIME" '%z'
|
|
|
|
check_show 'format-local:%%z' "$TIME" '%z'
|
|
|
|
|
2017-06-15 21:51:22 +08:00
|
|
|
check_show 'format:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 16:13:20'
|
|
|
|
check_show 'format-local:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 09:13:20' '' EST5
|
|
|
|
|
local_tzoffset: detect errors from tm_to_time_t
When we want to know the local timezone offset at a given
timestamp, we compute it by asking for localtime() at the
given time, and comparing the offset to GMT at that time.
However, there's some juggling between time_t and "struct
tm" which happens, which involves calling our own
tm_to_time_t().
If that function returns an error (e.g., because it only
handles dates up to the year 2099), it returns "-1", which
we treat as a time_t, and is clearly bogus, leading to
bizarre timestamps (that seem to always adjust the time back
to (time_t)(uint32_t)-1, in the year 2106).
It's not a good idea for local_tzoffset() to simply die
here; it would make it hard to run "git log" on a repository
with funny timestamps. Instead, let's just treat such cases
as "zero offset".
Reported-by: Norbert Kiesel <nkiesel@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-21 05:14:14 +08:00
|
|
|
# arbitrary time absurdly far in the future
|
|
|
|
FUTURE="5758122296 -0400"
|
2017-04-21 04:58:21 +08:00
|
|
|
check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT
|
|
|
|
check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" TIME_IS_64BIT,TIME_T_IS_64BIT
|
local_tzoffset: detect errors from tm_to_time_t
When we want to know the local timezone offset at a given
timestamp, we compute it by asking for localtime() at the
given time, and comparing the offset to GMT at that time.
However, there's some juggling between time_t and "struct
tm" which happens, which involves calling our own
tm_to_time_t().
If that function returns an error (e.g., because it only
handles dates up to the year 2099), it returns "-1", which
we treat as a time_t, and is clearly bogus, leading to
bizarre timestamps (that seem to always adjust the time back
to (time_t)(uint32_t)-1, in the year 2106).
It's not a good idea for local_tzoffset() to simply die
here; it would make it hard to run "git log" on a repository
with funny timestamps. Instead, let's just treat such cases
as "zero offset".
Reported-by: Norbert Kiesel <nkiesel@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-21 05:14:14 +08:00
|
|
|
|
2009-08-31 10:30:16 +08:00
|
|
|
check_parse() {
|
|
|
|
echo "$1 -> $2" >expect
|
2010-07-04 18:48:35 +08:00
|
|
|
test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" "
|
2018-03-24 15:44:36 +08:00
|
|
|
TZ=${3:-$TZ} test-tool date parse '$1' >actual &&
|
2009-08-31 10:30:16 +08:00
|
|
|
test_cmp expect actual
|
|
|
|
"
|
|
|
|
}
|
|
|
|
|
|
|
|
check_parse 2008 bad
|
|
|
|
check_parse 2008-02 bad
|
|
|
|
check_parse 2008-02-14 bad
|
|
|
|
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
|
2010-07-04 18:48:35 +08:00
|
|
|
check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
|
2011-09-09 18:10:33 +08:00
|
|
|
check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015'
|
|
|
|
check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 +0000'
|
|
|
|
check_parse '2008-02-14 20:30:45 -5:' '2008-02-14 20:30:45 +0000'
|
|
|
|
check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500'
|
|
|
|
check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
|
|
|
|
check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
|
2010-07-07 07:34:20 +08:00
|
|
|
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
|
2009-08-31 10:30:16 +08:00
|
|
|
|
|
|
|
check_approxidate() {
|
|
|
|
echo "$1 -> $2 +0000" >expect
|
|
|
|
test_expect_${3:-success} "parse approxidate ($1)" "
|
2018-03-24 15:44:36 +08:00
|
|
|
test-tool date approxidate '$1' >actual &&
|
2009-08-31 10:30:16 +08:00
|
|
|
test_cmp expect actual
|
|
|
|
"
|
|
|
|
}
|
|
|
|
|
|
|
|
check_approxidate now '2009-08-30 19:20:00'
|
|
|
|
check_approxidate '5 seconds ago' '2009-08-30 19:19:55'
|
|
|
|
check_approxidate 5.seconds.ago '2009-08-30 19:19:55'
|
|
|
|
check_approxidate 10.minutes.ago '2009-08-30 19:10:00'
|
|
|
|
check_approxidate yesterday '2009-08-29 19:20:00'
|
|
|
|
check_approxidate 3.days.ago '2009-08-27 19:20:00'
|
|
|
|
check_approxidate 3.weeks.ago '2009-08-09 19:20:00'
|
2009-08-31 10:31:42 +08:00
|
|
|
check_approxidate 3.months.ago '2009-05-30 19:20:00'
|
|
|
|
check_approxidate 2.years.3.months.ago '2007-05-30 19:20:00'
|
2009-08-31 10:30:16 +08:00
|
|
|
|
|
|
|
check_approxidate '6am yesterday' '2009-08-29 06:00:00'
|
|
|
|
check_approxidate '6pm yesterday' '2009-08-29 18:00:00'
|
|
|
|
check_approxidate '3:00' '2009-08-30 03:00:00'
|
|
|
|
check_approxidate '15:00' '2009-08-30 15:00:00'
|
|
|
|
check_approxidate 'noon today' '2009-08-30 12:00:00'
|
|
|
|
check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
|
|
|
|
|
|
|
|
check_approxidate 'last tuesday' '2009-08-25 19:20:00'
|
|
|
|
check_approxidate 'July 5th' '2009-07-05 19:20:00'
|
|
|
|
check_approxidate '06/05/2009' '2009-06-05 19:20:00'
|
|
|
|
check_approxidate '06.05.2009' '2009-05-06 19:20:00'
|
|
|
|
|
|
|
|
check_approxidate 'Jun 6, 5AM' '2009-06-06 05:00:00'
|
|
|
|
check_approxidate '5AM Jun 6' '2009-06-06 05:00:00'
|
|
|
|
check_approxidate '6AM, June 7, 2009' '2009-06-07 06:00:00'
|
|
|
|
|
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), 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[1,2].
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.
[1] http://en.wikipedia.org/wiki/Date_and_time_representation_by_country
[2] http://en.wikipedia.org/wiki/Calendar_date
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-14 05:43:31 +08:00
|
|
|
check_approxidate '2008-12-01' '2008-12-01 19:20:00'
|
|
|
|
check_approxidate '2009-12-01' '2009-12-01 19:20:00'
|
|
|
|
|
2009-08-31 10:30:16 +08:00
|
|
|
test_done
|