annotate mercurial/utils/dateutil.py @ 51285:9d3721552b6c

pytype: import typing directly First we no longer needs the pycompat layer, second having the types imported in all case will allow to use them more directly in type annotation, something important to upgrade the old "type comment" to proper type annotation. A lot a stupid assert are needed to keep pyflakes happy. We should be able to remove most of them once the type comment have been upgraded.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 20 Dec 2023 12:51:20 +0100
parents faccec1edc2c
children f15cb5111a1e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36588
diff changeset
1 # util.py - Mercurial utility functions relative to dates
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
2 #
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36588
diff changeset
3 # Copyright 2018 Boris Feld <boris.feld@octobus.net>
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
4 #
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9996
diff changeset
6 # GNU General Public License version 2 or any later version.
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
7
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
8
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
9 import calendar
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
10 import datetime
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
11 import time
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
12
51285
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
13 from typing import (
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
14 Callable,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
15 Dict,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
16 Iterable,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
17 Optional,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
18 Tuple,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
19 Union,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
20 )
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
21
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36588
diff changeset
22 from ..i18n import _
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36588
diff changeset
23 from .. import (
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
24 encoding,
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
25 error,
28818
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents: 28497
diff changeset
26 pycompat,
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
27 )
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
28
51285
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
29 # keeps pyflakes happy
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
30 assert [
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
31 Callable,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
32 Dict,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
33 Iterable,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
34 Optional,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
35 Tuple,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
36 Union,
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
37 ]
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
38
51285
9d3721552b6c pytype: import typing directly
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50752
diff changeset
39 hgdate = Tuple[float, int] # (unixtime, offset)
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
40
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
41 # used by parsedate
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
42 defaultdateformats = (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
43 b'%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
44 b'%Y-%m-%dT%H:%M', # without seconds
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
45 b'%Y-%m-%dT%H%M%S', # another awful but legal variant without :
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
46 b'%Y-%m-%dT%H%M', # without seconds
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
47 b'%Y-%m-%d %H:%M:%S', # our common legal variant
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
48 b'%Y-%m-%d %H:%M', # without seconds
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
49 b'%Y-%m-%d %H%M%S', # without :
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
50 b'%Y-%m-%d %H%M', # without seconds
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
51 b'%Y-%m-%d %I:%M:%S%p',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
52 b'%Y-%m-%d %H:%M',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
53 b'%Y-%m-%d %I:%M%p',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
54 b'%Y-%m-%d',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
55 b'%m-%d',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
56 b'%m/%d',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
57 b'%m/%d/%y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
58 b'%m/%d/%Y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
59 b'%a %b %d %H:%M:%S %Y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
60 b'%a %b %d %I:%M:%S%p %Y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
61 b'%a, %d %b %Y %H:%M:%S', # GNU coreutils "/bin/date --rfc-2822"
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
62 b'%b %d %H:%M:%S %Y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
63 b'%b %d %I:%M:%S%p %Y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
64 b'%b %d %H:%M:%S',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
65 b'%b %d %I:%M:%S%p',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
66 b'%b %d %H:%M',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
67 b'%b %d %I:%M%p',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
68 b'%b %d %Y',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
69 b'%b %d',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
70 b'%H:%M:%S',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
71 b'%I:%M:%S%p',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
72 b'%H:%M',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
73 b'%I:%M%p',
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
74 )
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
75
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
76 extendeddateformats = defaultdateformats + (
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
77 b"%Y",
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
78 b"%Y-%m",
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
79 b"%b",
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
80 b"%b %Y",
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
81 )
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
82
36362
01e29e885600 util: add a file object proxy that can read at most N bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36266
diff changeset
83
19287
8b04e1344111 util: add an optional timestamp parameter to makedate
Bryan O'Sullivan <bryano@fb.com>
parents: 19286
diff changeset
84 def makedate(timestamp=None):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
85 # type: (Optional[float]) -> hgdate
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
86 """Return a unix timestamp (or the current time) as a (unixtime,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
87 offset) tuple based off the local timezone."""
19287
8b04e1344111 util: add an optional timestamp parameter to makedate
Bryan O'Sullivan <bryano@fb.com>
parents: 19286
diff changeset
88 if timestamp is None:
8b04e1344111 util: add an optional timestamp parameter to makedate
Bryan O'Sullivan <bryano@fb.com>
parents: 19286
diff changeset
89 timestamp = time.time()
19286
78501209488a util: rename ct variable in makedate to timestamp
Bryan O'Sullivan <bryano@fb.com>
parents: 19211
diff changeset
90 if timestamp < 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
91 hint = _(b"check your clock")
46419
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
92 raise error.InputError(
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
93 _(b"negative timestamp: %d") % timestamp, hint=hint
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
94 )
50752
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
95 tz = round(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
96 timestamp
50752
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
97 - datetime.datetime.fromtimestamp(
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
98 timestamp,
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
99 )
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
100 .replace(tzinfo=datetime.timezone.utc)
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
101 .timestamp()
faccec1edc2c utils: stop using datetime.utcfromtimestamp() deprecated in Python 3.12
Mads Kiilerich <mads@kiilerich.com>
parents: 48875
diff changeset
102 )
19286
78501209488a util: rename ct variable in makedate to timestamp
Bryan O'Sullivan <bryano@fb.com>
parents: 19211
diff changeset
103 return timestamp, tz
1329
8f06817bf266 Allow files to be opened in text mode, even on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1321
diff changeset
104
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
105
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
106 def datestr(date=None, format=b'%a %b %d %H:%M:%S %Y %1%2'):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
107 # type: (Optional[hgdate], bytes) -> bytes
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
108 """represent a (unixtime, offset) tuple as a localized time.
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
109 unixtime is seconds since the epoch, and offset is the time zone's
28865
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
110 number of seconds away from UTC.
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
111
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
112 >>> datestr((0, 0))
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
113 'Thu Jan 01 00:00:00 1970 +0000'
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
114 >>> datestr((42, 0))
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
115 'Thu Jan 01 00:00:42 1970 +0000'
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
116 >>> datestr((-42, 0))
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
117 'Wed Dec 31 23:59:18 1969 +0000'
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
118 >>> datestr((0x7fffffff, 0))
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
119 'Tue Jan 19 03:14:07 2038 +0000'
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
120 >>> datestr((-0x80000000, 0))
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
121 'Fri Dec 13 20:45:52 1901 +0000'
16255662446d util: add doctest to datestr()
Adrian Buehlmann <adrian@cadifra.com>
parents: 28864
diff changeset
122 """
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
123 t, tz = date or makedate()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
124 if b"%1" in format or b"%2" in format or b"%z" in format:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
125 sign = (tz > 0) and b"-" or b"+"
9029
0001e49f1c11 compat: use // for integer division
Alejandro Santos <alejolp@alejolp.com>
parents: 8938
diff changeset
126 minutes = abs(tz) // 60
27066
6f1f8e88f036 util.datestr: use divmod()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27016
diff changeset
127 q, r = divmod(minutes, 60)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
128 format = format.replace(b"%z", b"%1%2")
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
129 format = format.replace(b"%1", b"%c%02d" % (sign, q))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
130 format = format.replace(b"%2", b"%02d" % r)
28825
87c6ad2251d8 date: reallow negative timestamp, fix for Windows buggy gmtime() (issue2513)
Florent Gallaire <fgallaire@gmail.com>
parents: 28818
diff changeset
131 d = t - tz
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
132 if d > 0x7FFFFFFF:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
133 d = 0x7FFFFFFF
28864
b0811a9fe67c date: fix boundary check of negative integer
Florent Gallaire <fgallaire@gmail.com>
parents: 28835
diff changeset
134 elif d < -0x80000000:
b0811a9fe67c date: fix boundary check of negative integer
Florent Gallaire <fgallaire@gmail.com>
parents: 28835
diff changeset
135 d = -0x80000000
28825
87c6ad2251d8 date: reallow negative timestamp, fix for Windows buggy gmtime() (issue2513)
Florent Gallaire <fgallaire@gmail.com>
parents: 28818
diff changeset
136 # Never use time.gmtime() and datetime.datetime.fromtimestamp()
87c6ad2251d8 date: reallow negative timestamp, fix for Windows buggy gmtime() (issue2513)
Florent Gallaire <fgallaire@gmail.com>
parents: 28818
diff changeset
137 # because they use the gmtime() system call which is buggy on Windows
87c6ad2251d8 date: reallow negative timestamp, fix for Windows buggy gmtime() (issue2513)
Florent Gallaire <fgallaire@gmail.com>
parents: 28818
diff changeset
138 # for negative values.
87c6ad2251d8 date: reallow negative timestamp, fix for Windows buggy gmtime() (issue2513)
Florent Gallaire <fgallaire@gmail.com>
parents: 28818
diff changeset
139 t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d)
31449
756175623f2e py3: call strftime() with native str type
Yuya Nishihara <yuya@tcha.org>
parents: 31448
diff changeset
140 s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format)))
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
141 return s
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
142
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
143
6134
7b937b26adf7 Make annotae/grep print short dates with -q/--quiet.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6111
diff changeset
144 def shortdate(date=None):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
145 # type: (Optional[hgdate]) -> bytes
6134
7b937b26adf7 Make annotae/grep print short dates with -q/--quiet.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6111
diff changeset
146 """turn (timestamp, tzoff) tuple into iso 8631 date."""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
147 return datestr(date, format=b'%Y-%m-%d')
6134
7b937b26adf7 Make annotae/grep print short dates with -q/--quiet.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6111
diff changeset
148
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
149
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
150 def parsetimezone(s):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
151 # type: (bytes) -> Tuple[Optional[int], bytes]
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
152 """find a trailing timezone, if any, in string, and return a
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43781
diff changeset
153 (offset, remainder) pair"""
36551
98d4c642d7f2 py3: fix string slicing in util.parsetimezone()
Yuya Nishihara <yuya@tcha.org>
parents: 36539
diff changeset
154 s = pycompat.bytestr(s)
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
155
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
156 if s.endswith(b"GMT") or s.endswith(b"UTC"):
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
157 return 0, s[:-3].rstrip()
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
158
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
159 # Unix-style timezones [+-]hhmm
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
160 if len(s) >= 5 and s[-5] in b"+-" and s[-4:].isdigit():
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
161 sign = (s[-5] == b"+") and 1 or -1
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
162 hours = int(s[-4:-2])
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
163 minutes = int(s[-2:])
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
164 return -sign * (hours * 60 + minutes) * 60, s[:-5].rstrip()
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
165
29637
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
166 # ISO8601 trailing Z
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
167 if s.endswith(b"Z") and s[-2:-1].isdigit():
29637
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
168 return 0, s[:-1]
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
169
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
170 # ISO8601-style [+-]hh:mm
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
171 if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
172 len(s) >= 6
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
173 and s[-6] in b"+-"
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
174 and s[-3] == b":"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
175 and s[-5:-3].isdigit()
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
176 and s[-2:].isdigit()
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
177 ):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
178 sign = (s[-6] == b"+") and 1 or -1
29637
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
179 hours = int(s[-5:-3])
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
180 minutes = int(s[-2:])
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
181 return -sign * (hours * 60 + minutes) * 60, s[:-6]
46b2ccce7fde date: parse ISO-style Z and +hh:mm timezone specs
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
182
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
183 return None, s
26126
7b625baed995 util: extract function that parses timezone string
Yuya Nishihara <yuya@tcha.org>
parents: 26098
diff changeset
184
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
185
31393
8b6927eb7efd util: don't use mutable default argument value
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31368
diff changeset
186 def strdate(string, format, defaults=None):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
187 # type: (bytes, bytes, Optional[Dict[bytes, Tuple[bytes, bytes]]]) -> hgdate
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
188 """parse a localized time string and return a (unixtime, offset) tuple.
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
189 if the string cannot be parsed, ValueError is raised."""
31465
da83f12d7a88 util: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31453
diff changeset
190 if defaults is None:
da83f12d7a88 util: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31453
diff changeset
191 defaults = {}
31393
8b6927eb7efd util: don't use mutable default argument value
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31368
diff changeset
192
3255
e96d2956eb4a util.strdate: compute timestamp using UTC, not local timezone
Jose M. Prieto <jmprieto@gmx.net>
parents: 3176
diff changeset
193 # NOTE: unixtime = localunixtime + offset
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29613
diff changeset
194 offset, date = parsetimezone(string)
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
195
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
196 # add missing elements from defaults
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
197 usenow = False # default to using biased defaults
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
198 for part in (
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
199 b"S",
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
200 b"M",
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
201 b"HI",
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
202 b"d",
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
203 b"mb",
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
204 b"yY",
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
205 ): # decreasing specificity
32154
52e222eef646 py3: use pycompat.bytestr instead of bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32153
diff changeset
206 part = pycompat.bytestr(part)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
207 found = [True for p in part if (b"%" + p) in format]
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
208 if not found:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
209 date += b"@" + defaults[part][usenow]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
210 format += b"@%" + part[0]
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
211 else:
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
212 # We've found a specific time element, less specific time
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
213 # elements are relative to today
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
214 usenow = True
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
215
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
216 timetuple = time.strptime(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
217 encoding.strfromlocal(date), encoding.strfromlocal(format)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
218 )
3256
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
219 localunixtime = int(calendar.timegm(timetuple))
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
220 if offset is None:
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
221 # local timezone
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
222 unixtime = int(time.mktime(timetuple))
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
223 offset = unixtime - localunixtime
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
224 else:
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
225 unixtime = localunixtime + offset
3255
e96d2956eb4a util.strdate: compute timestamp using UTC, not local timezone
Jose M. Prieto <jmprieto@gmx.net>
parents: 3176
diff changeset
226 return unixtime, offset
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
227
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
228
26311
60dd8e3977f0 util: avoid mutable default arguments
Siddharth Agarwal <sid0@fb.com>
parents: 26267
diff changeset
229 def parsedate(date, formats=None, bias=None):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
230 # type: (Union[bytes, hgdate], Optional[Iterable[bytes]], Optional[Dict[bytes, bytes]]) -> hgdate
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
231 """parse a localized date/time and return a (unixtime, offset) tuple.
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
232
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
233 The date may be a "unixtime offset" string or in one of the specified
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
234 formats. If the date already is a (unixtime, offset) tuple, it is returned.
18537
ae60735e37d2 dates: support 'today' and 'yesterday' in parsedate (issue3764)
Paul Cavallaro <ptc@fb.com>
parents: 18326
diff changeset
235
34362
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
236 >>> parsedate(b' today ') == parsedate(
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
237 ... datetime.date.today().strftime('%b %d').encode('ascii'))
18537
ae60735e37d2 dates: support 'today' and 'yesterday' in parsedate (issue3764)
Paul Cavallaro <ptc@fb.com>
parents: 18326
diff changeset
238 True
34362
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
239 >>> parsedate(b'yesterday ') == parsedate(
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
240 ... (datetime.date.today() - datetime.timedelta(days=1)
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
241 ... ).strftime('%b %d').encode('ascii'))
18537
ae60735e37d2 dates: support 'today' and 'yesterday' in parsedate (issue3764)
Paul Cavallaro <ptc@fb.com>
parents: 18326
diff changeset
242 True
18614
b2586e2cc67a parsedate: understand "now" as a shortcut for the current time
Augie Fackler <raf@durin42.com>
parents: 18603
diff changeset
243 >>> now, tz = makedate()
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
244 >>> strnow, strtz = parsedate(b'now')
18614
b2586e2cc67a parsedate: understand "now" as a shortcut for the current time
Augie Fackler <raf@durin42.com>
parents: 18603
diff changeset
245 >>> (strnow - now) < 1
b2586e2cc67a parsedate: understand "now" as a shortcut for the current time
Augie Fackler <raf@durin42.com>
parents: 18603
diff changeset
246 True
b2586e2cc67a parsedate: understand "now" as a shortcut for the current time
Augie Fackler <raf@durin42.com>
parents: 18603
diff changeset
247 >>> tz == strtz
b2586e2cc67a parsedate: understand "now" as a shortcut for the current time
Augie Fackler <raf@durin42.com>
parents: 18603
diff changeset
248 True
43781
b65bd4b61d78 dateutil: correct default for Ymd in parsedate
Jun Wu <quark@fb.com>
parents: 43506
diff changeset
249 >>> parsedate(b'2000 UTC', formats=extendeddateformats)
b65bd4b61d78 dateutil: correct default for Ymd in parsedate
Jun Wu <quark@fb.com>
parents: 43506
diff changeset
250 (946684800, 0)
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
251 """
26311
60dd8e3977f0 util: avoid mutable default arguments
Siddharth Agarwal <sid0@fb.com>
parents: 26267
diff changeset
252 if bias is None:
60dd8e3977f0 util: avoid mutable default arguments
Siddharth Agarwal <sid0@fb.com>
parents: 26267
diff changeset
253 bias = {}
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
254 if not date:
3807
e43b48f0f718 parsedate: allow '' for epoch
Matt Mackall <mpm@selenic.com>
parents: 3806
diff changeset
255 return 0, 0
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
256 if isinstance(date, tuple):
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
257 if len(date) == 2:
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
258 return date
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
259 else:
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
260 raise error.ProgrammingError(b"invalid date format")
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
261 if not formats:
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
262 formats = defaultdateformats
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
263 date = date.strip()
18537
ae60735e37d2 dates: support 'today' and 'yesterday' in parsedate (issue3764)
Paul Cavallaro <ptc@fb.com>
parents: 18326
diff changeset
264
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
265 if date == b'now' or date == _(b'now'):
18614
b2586e2cc67a parsedate: understand "now" as a shortcut for the current time
Augie Fackler <raf@durin42.com>
parents: 18603
diff changeset
266 return makedate()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
267 if date == b'today' or date == _(b'today'):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43077
diff changeset
268 date = datetime.date.today().strftime('%b %d')
34362
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
269 date = encoding.strtolocal(date)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
270 elif date == b'yesterday' or date == _(b'yesterday'):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
271 date = (datetime.date.today() - datetime.timedelta(days=1)).strftime(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
272 r'%b %d'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
273 )
34362
b76937fafe8a py3: work around bytes/unicode divergence in parsedate()
Yuya Nishihara <yuya@tcha.org>
parents: 34361
diff changeset
274 date = encoding.strtolocal(date)
18537
ae60735e37d2 dates: support 'today' and 'yesterday' in parsedate (issue3764)
Paul Cavallaro <ptc@fb.com>
parents: 18326
diff changeset
275
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
276 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
277 when, offset = map(int, date.split(b' '))
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
278 except ValueError:
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
279 # fill out defaults
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
280 now = makedate()
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
281 defaults = {}
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
282 for part in (b"d", b"mb", b"yY", b"HI", b"M", b"S"):
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
283 # this piece is for rounding the specific end of unknowns
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
284 b = bias.get(part)
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
285 if b is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
286 if part[0:1] in b"HMS":
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
287 b = b"00"
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
288 else:
43781
b65bd4b61d78 dateutil: correct default for Ymd in parsedate
Jun Wu <quark@fb.com>
parents: 43506
diff changeset
289 # year, month, and day start from 1
b65bd4b61d78 dateutil: correct default for Ymd in parsedate
Jun Wu <quark@fb.com>
parents: 43506
diff changeset
290 b = b"1"
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
291
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
292 # this piece is for matching the generic end to today's date
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
293 n = datestr(now, b"%" + part[0:1])
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
294
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
295 defaults[part] = (b, n)
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
296
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
297 for format in formats:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
298 try:
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
299 when, offset = strdate(date, format, defaults)
6087
12856a1742dc better handle errors with date parsing (issue983)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5917
diff changeset
300 except (ValueError, OverflowError):
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
301 pass
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
302 else:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
303 break
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
304 else:
36539
0c2eeaca0577 util: use pycompat.bytestr() on repr() in date parse abort
Augie Fackler <augie@google.com>
parents: 36525
diff changeset
305 raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
306 _(b'invalid date: %r') % pycompat.bytestr(date)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
307 )
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
308 # validate explicit (probably user-specified) date and
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
309 # time zone offset. values must fit in signed 32 bits for
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
310 # current 32-bit linux runtimes. timezones go from UTC-12
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
311 # to UTC+14
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
312 if when < -0x80000000 or when > 0x7FFFFFFF:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
313 raise error.ParseError(_(b'date exceeds 32 bits: %d') % when)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
314 if offset < -50400 or offset > 43200:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
315 raise error.ParseError(_(b'impossible time zone offset: %d') % offset)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
316 return when, offset
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
317
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
318
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
319 def matchdate(date):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
320 # type: (bytes) -> Callable[[float], bool]
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
321 """Return a function that matches a given date match specifier
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
322
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
323 Formats include:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
324
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
325 '{date}' match a given date to the accuracy provided
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
326
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
327 '<{date}' on or before a given date
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
328
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
329 '>{date}' on or after a given date
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
330
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
331 >>> p1 = parsedate(b"10:29:59")
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
332 >>> p2 = parsedate(b"10:30:00")
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
333 >>> p3 = parsedate(b"10:30:59")
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
334 >>> p4 = parsedate(b"10:31:00")
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
335 >>> p5 = parsedate(b"Sep 15 10:30:00 1999")
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34084
diff changeset
336 >>> f = matchdate(b"10:30")
13212
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
337 >>> f(p1[0])
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
338 False
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
339 >>> f(p2[0])
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
340 True
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
341 >>> f(p3[0])
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
342 True
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
343 >>> f(p4[0])
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
344 False
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
345 >>> f(p5[0])
5d0a30fad7de date: fix matching of underspecified date ranges
Matt Mackall <mpm@selenic.com>
parents: 13204
diff changeset
346 False
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
347 """
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
348
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
349 def lower(date):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
350 # type: (bytes) -> float
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
351 d = {b'mb': b"1", b'd': b"1"}
6230
c7253d1a774e dates: Fix bare times to be relative to "today"
Matt Mackall <mpm@selenic.com>
parents: 6229
diff changeset
352 return parsedate(date, extendeddateformats, d)[0]
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
353
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
354 def upper(date):
46641
15c2f9220ae8 typing: add type annotations to mercurial/utils/dateutil.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 46419
diff changeset
355 # type: (bytes) -> float
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
356 d = {b'mb': b"12", b'HI': b"23", b'M': b"59", b'S': b"59"}
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
357 for days in (b"31", b"30", b"29"):
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
358 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
359 d[b"d"] = days
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
360 return parsedate(date, extendeddateformats, d)[0]
36234
48783333f45c date: fix parsing months
Jun Wu <quark@fb.com>
parents: 35755
diff changeset
361 except error.ParseError:
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
362 pass
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
363 d[b"d"] = b"28"
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
364 return parsedate(date, extendeddateformats, d)[0]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
365
7953
8c6f823efcc9 Correct a bug on date formats with '>' or '<' accompanied by space characters.
Justin Peng <justin.peng.sw@gmail.com>
parents: 7948
diff changeset
366 date = date.strip()
13780
bc7b5d1c1999 util: dates cannot consist entirely of whitespace (issue2732)
Idan Kamara <idankk86@gmail.com>
parents: 13734
diff changeset
367
bc7b5d1c1999 util: dates cannot consist entirely of whitespace (issue2732)
Idan Kamara <idankk86@gmail.com>
parents: 13734
diff changeset
368 if not date:
46419
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
369 raise error.InputError(
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
370 _(b"dates cannot consist entirely of whitespace")
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
371 )
40256
d4d2c567bb72 py3: fix test-parse-date.t
Mark Thomas <mbthomas@fb.com>
parents: 36607
diff changeset
372 elif date[0:1] == b"<":
13869
b470894c33f8 date: fixup breakage from ">" fix
Matt Mackall <mpm@selenic.com>
parents: 13867
diff changeset
373 if not date[1:]:
46419
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
374 raise error.InputError(_(b"invalid day spec, use '<DATE'"))
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
375 when = upper(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
376 return lambda x: x <= when
40256
d4d2c567bb72 py3: fix test-parse-date.t
Mark Thomas <mbthomas@fb.com>
parents: 36607
diff changeset
377 elif date[0:1] == b">":
13869
b470894c33f8 date: fixup breakage from ">" fix
Matt Mackall <mpm@selenic.com>
parents: 13867
diff changeset
378 if not date[1:]:
46419
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
379 raise error.InputError(_(b"invalid day spec, use '>DATE'"))
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
380 when = lower(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
381 return lambda x: x >= when
40256
d4d2c567bb72 py3: fix test-parse-date.t
Mark Thomas <mbthomas@fb.com>
parents: 36607
diff changeset
382 elif date[0:1] == b"-":
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
383 try:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
384 days = int(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
385 except ValueError:
46419
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
386 raise error.InputError(_(b"invalid day spec: %s") % date[1:])
13889
9a96efc4af8a util: make 'hg log -d --2' abort (issue2734)
Yun Lee <yunlee.bj@gmail.com>
parents: 13886
diff changeset
387 if days < 0:
46419
6894c9ef4dcd errors: use InputError for incorrectly formatted dates
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
388 raise error.InputError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
389 _(b"%s must be nonnegative (see 'hg help dates')") % date[1:]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40256
diff changeset
390 )
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
391 when = makedate()[0] - days * 3600 * 24
3813
fc5ba0ab7f45 Add --date support to log
Matt Mackall <mpm@selenic.com>
parents: 3812
diff changeset
392 return lambda x: x >= when
40256
d4d2c567bb72 py3: fix test-parse-date.t
Mark Thomas <mbthomas@fb.com>
parents: 36607
diff changeset
393 elif b" to " in date:
d4d2c567bb72 py3: fix test-parse-date.t
Mark Thomas <mbthomas@fb.com>
parents: 36607
diff changeset
394 a, b = date.split(b" to ")
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
395 start, stop = lower(a), upper(b)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
396 return lambda x: x >= start and x <= stop
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
397 else:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
398 start, stop = lower(date), upper(date)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
399 return lambda x: x >= start and x <= stop