D2055: util: extract parsedate
lothiraldan (Boris Feld)
phabricator at mercurial-scm.org
Mon Feb 5 16:26:19 UTC 2018
lothiraldan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
Extract parsedate from util.py to utils/dateutil.py
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D2055
AFFECTED FILES
hgext/convert/convcmd.py
hgext/convert/cvsps.py
hgext/convert/subversion.py
hgext/fetch.py
hgext/gpg.py
hgext/keyword.py
hgext/mq.py
hgext/patchbomb.py
mercurial/changelog.py
mercurial/cmdutil.py
mercurial/commands.py
mercurial/context.py
mercurial/debugcommands.py
mercurial/obsolete.py
mercurial/templater.py
mercurial/ui.py
mercurial/util.py
mercurial/utils/dateutil.py
tests/fakedirstatewritetime.py
tests/fakepatchtime.py
CHANGE DETAILS
diff --git a/tests/fakepatchtime.py b/tests/fakepatchtime.py
--- a/tests/fakepatchtime.py
+++ b/tests/fakepatchtime.py
@@ -7,8 +7,8 @@
extensions,
patch as patchmod,
registrar,
- util,
)
+from mercurial.utils import dateutil
configtable = {}
configitem = registrar.configitem(configtable)
@@ -30,7 +30,7 @@
if fakenow:
# parsing 'fakenow' in YYYYmmddHHMM format makes comparison between
# 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy
- fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0]
+ fakenow = dateutil.parsedate(fakenow, ['%Y%m%d%H%M'])[0]
for f in files:
repo.wvfs.utime(f, (fakenow, fakenow))
diff --git a/tests/fakedirstatewritetime.py b/tests/fakedirstatewritetime.py
--- a/tests/fakedirstatewritetime.py
+++ b/tests/fakedirstatewritetime.py
@@ -13,8 +13,8 @@
extensions,
policy,
registrar,
- util,
)
+from mercurial.utils import dateutil
configtable = {}
configitem = registrar.configitem(configtable)
@@ -49,7 +49,7 @@
# parsing 'fakenow' in YYYYmmddHHMM format makes comparison between
# 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy
- fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0]
+ fakenow = dateutil.parsedate(fakenow, ['%Y%m%d%H%M'])[0]
orig_pack_dirstate = parsers.pack_dirstate
orig_dirstate_getfsnow = dirstate._getfsnow
diff --git a/mercurial/utils/dateutil.py b/mercurial/utils/dateutil.py
--- a/mercurial/utils/dateutil.py
+++ b/mercurial/utils/dateutil.py
@@ -174,3 +174,82 @@
unixtime = localunixtime + offset
return unixtime, offset
+def parsedate(date, formats=None, bias=None):
+ """parse a localized date/time and return a (unixtime, offset) tuple.
+
+ The date may be a "unixtime offset" string or in one of the specified
+ formats. If the date already is a (unixtime, offset) tuple, it is returned.
+
+ >>> parsedate(b' today ') == parsedate(
+ ... datetime.date.today().strftime('%b %d').encode('ascii'))
+ True
+ >>> parsedate(b'yesterday ') == parsedate(
+ ... (datetime.date.today() - datetime.timedelta(days=1)
+ ... ).strftime('%b %d').encode('ascii'))
+ True
+ >>> now, tz = makedate()
+ >>> strnow, strtz = parsedate(b'now')
+ >>> (strnow - now) < 1
+ True
+ >>> tz == strtz
+ True
+ """
+ if bias is None:
+ bias = {}
+ if not date:
+ return 0, 0
+ if isinstance(date, tuple) and len(date) == 2:
+ return date
+ if not formats:
+ formats = defaultdateformats
+ date = date.strip()
+
+ if date == 'now' or date == _('now'):
+ return makedate()
+ if date == 'today' or date == _('today'):
+ date = datetime.date.today().strftime(r'%b %d')
+ date = encoding.strtolocal(date)
+ elif date == 'yesterday' or date == _('yesterday'):
+ date = (datetime.date.today() -
+ datetime.timedelta(days=1)).strftime(r'%b %d')
+ date = encoding.strtolocal(date)
+
+ try:
+ when, offset = map(int, date.split(' '))
+ except ValueError:
+ # fill out defaults
+ now = makedate()
+ defaults = {}
+ for part in ("d", "mb", "yY", "HI", "M", "S"):
+ # this piece is for rounding the specific end of unknowns
+ b = bias.get(part)
+ if b is None:
+ if part[0:1] in "HMS":
+ b = "00"
+ else:
+ b = "0"
+
+ # this piece is for matching the generic end to today's date
+ n = datestr(now, "%" + part[0:1])
+
+ defaults[part] = (b, n)
+
+ for format in formats:
+ try:
+ when, offset = strdate(date, format, defaults)
+ except (ValueError, OverflowError):
+ pass
+ else:
+ break
+ else:
+ raise error.ParseError(_('invalid date: %r') % date)
+ # validate explicit (probably user-specified) date and
+ # time zone offset. values must fit in signed 32 bits for
+ # current 32-bit linux runtimes. timezones go from UTC-12
+ # to UTC+14
+ if when < -0x80000000 or when > 0x7fffffff:
+ raise error.ParseError(_('date exceeds 32 bits: %d') % when)
+ if offset < -50400 or offset > 43200:
+ raise error.ParseError(_('impossible time zone offset: %d') % offset)
+ return when, offset
+
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -20,7 +20,6 @@
import codecs
import collections
import contextlib
-import datetime
import errno
import gc
import hashlib
@@ -1905,85 +1904,6 @@
limit -= len(s)
yield s
-def parsedate(date, formats=None, bias=None):
- """parse a localized date/time and return a (unixtime, offset) tuple.
-
- The date may be a "unixtime offset" string or in one of the specified
- formats. If the date already is a (unixtime, offset) tuple, it is returned.
-
- >>> parsedate(b' today ') == parsedate(
- ... datetime.date.today().strftime('%b %d').encode('ascii'))
- True
- >>> parsedate(b'yesterday ') == parsedate(
- ... (datetime.date.today() - datetime.timedelta(days=1)
- ... ).strftime('%b %d').encode('ascii'))
- True
- >>> now, tz = dateutil.makedate()
- >>> strnow, strtz = parsedate(b'now')
- >>> (strnow - now) < 1
- True
- >>> tz == strtz
- True
- """
- if bias is None:
- bias = {}
- if not date:
- return 0, 0
- if isinstance(date, tuple) and len(date) == 2:
- return date
- if not formats:
- formats = defaultdateformats
- date = date.strip()
-
- if date == 'now' or date == _('now'):
- return dateutil.makedate()
- if date == 'today' or date == _('today'):
- date = datetime.date.today().strftime(r'%b %d')
- date = encoding.strtolocal(date)
- elif date == 'yesterday' or date == _('yesterday'):
- date = (datetime.date.today() -
- datetime.timedelta(days=1)).strftime(r'%b %d')
- date = encoding.strtolocal(date)
-
- try:
- when, offset = map(int, date.split(' '))
- except ValueError:
- # fill out defaults
- now = dateutil.makedate()
- defaults = {}
- for part in ("d", "mb", "yY", "HI", "M", "S"):
- # this piece is for rounding the specific end of unknowns
- b = bias.get(part)
- if b is None:
- if part[0:1] in "HMS":
- b = "00"
- else:
- b = "0"
-
- # this piece is for matching the generic end to today's date
- n = dateutil.datestr(now, "%" + part[0:1])
-
- defaults[part] = (b, n)
-
- for format in formats:
- try:
- when, offset = dateutil.strdate(date, format, defaults)
- except (ValueError, OverflowError):
- pass
- else:
- break
- else:
- raise error.ParseError(_('invalid date: %r') % date)
- # validate explicit (probably user-specified) date and
- # time zone offset. values must fit in signed 32 bits for
- # current 32-bit linux runtimes. timezones go from UTC-12
- # to UTC+14
- if when < -0x80000000 or when > 0x7fffffff:
- raise error.ParseError(_('date exceeds 32 bits: %d') % when)
- if offset < -50400 or offset > 43200:
- raise error.ParseError(_('impossible time zone offset: %d') % offset)
- return when, offset
-
def matchdate(date):
"""Return a function that matches a given date match specifier
@@ -1995,11 +1915,11 @@
'>{date}' on or after a given date
- >>> p1 = parsedate(b"10:29:59")
- >>> p2 = parsedate(b"10:30:00")
- >>> p3 = parsedate(b"10:30:59")
- >>> p4 = parsedate(b"10:31:00")
- >>> p5 = parsedate(b"Sep 15 10:30:00 1999")
+ >>> p1 = dateutil.parsedate(b"10:29:59")
+ >>> p2 = dateutil.parsedate(b"10:30:00")
+ >>> p3 = dateutil.parsedate(b"10:30:59")
+ >>> p4 = dateutil.parsedate(b"10:31:00")
+ >>> p5 = dateutil.parsedate(b"Sep 15 10:30:00 1999")
>>> f = matchdate(b"10:30")
>>> f(p1[0])
False
@@ -2015,18 +1935,18 @@
def lower(date):
d = {'mb': "1", 'd': "1"}
- return parsedate(date, extendeddateformats, d)[0]
+ return dateutil.parsedate(date, extendeddateformats, d)[0]
def upper(date):
d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"}
for days in ("31", "30", "29"):
try:
d["d"] = days
- return parsedate(date, extendeddateformats, d)[0]
+ return dateutil.parsedate(date, extendeddateformats, d)[0]
except Abort:
pass
d["d"] = "28"
- return parsedate(date, extendeddateformats, d)[0]
+ return dateutil.parsedate(date, extendeddateformats, d)[0]
date = date.strip()
@@ -3827,3 +3747,9 @@
nouideprecwarn(msg, "4.6")
return dateutil.strdate(*args, **kwargs)
+def parsedate(*args, **kwargs):
+ msg = ("'util.parsedate' is deprecated, "
+ "use 'utils.dateutil.parsedate'")
+ nouideprecwarn(msg, "4.6")
+ return dateutil.parsedate(*args, **kwargs)
+
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -37,6 +37,7 @@
scmutil,
util,
)
+from .utils import dateutil
urlreq = util.urlreq
@@ -722,7 +723,7 @@
(0, 0)
"""
if self.config(section, name, default, untrusted):
- return self.configwith(util.parsedate, section, name, default,
+ return self.configwith(dateutil.parsedate, section, name, default,
'date', untrusted)
if default is _unset:
return None
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -905,7 +905,7 @@
date = evalfuncarg(context, mapping, args[0])
try:
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
except AttributeError: # not str nor date tuple
# i18n: "localdate" is a keyword
raise error.ParseError(_("localdate expects a date information"))
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -609,7 +609,7 @@
if date is None:
if 'date' in metadata:
# as a courtesy for out-of-tree extensions
- date = util.parsedate(metadata.pop('date'))
+ date = dateutil.parsedate(metadata.pop('date'))
elif ui is not None:
date = ui.configdate('devel', 'default-date')
if date is None:
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -557,9 +557,9 @@
def debugdate(ui, date, range=None, **opts):
"""parse and display a date"""
if opts[r"extended"]:
- d = util.parsedate(date, util.extendeddateformats)
+ d = dateutil.parsedate(date, util.extendeddateformats)
else:
- d = util.parsedate(date)
+ d = dateutil.parsedate(date)
ui.write(("internal: %s %s\n") % d)
ui.write(("standard: %s\n") % dateutil.datestr(d))
if range:
@@ -1574,7 +1574,7 @@
try:
date = opts.get('date')
if date:
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
else:
date = None
prec = parsenodeid(precursor)
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1331,7 +1331,7 @@
self._node = None
self._text = text
if date:
- self._date = util.parsedate(date)
+ self._date = dateutil.parsedate(date)
if user:
self._user = user
if changes:
@@ -2448,7 +2448,7 @@
user receives the committer name and defaults to current
repository username, date is the commit date in any format
- supported by util.parsedate() and defaults to current date, extra
+ supported by dateutil.parsedate() and defaults to current date, extra
is a dictionary of metadata or is left empty.
"""
@@ -2663,7 +2663,7 @@
user receives the committer name and defaults to current repository
username, date is the commit date in any format supported by
- util.parsedate() and defaults to current date, extra is a dictionary of
+ dateutil.parsedate() and defaults to current date, extra is a dictionary of
metadata or is left empty.
"""
def __new__(cls, repo, originalctx, *args, **kwargs):
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -584,7 +584,7 @@
date = opts.get('date')
if date:
- opts['date'] = util.parsedate(date)
+ opts['date'] = dateutil.parsedate(date)
cmdutil.checkunfinished(repo)
cmdutil.bailifchanged(repo)
@@ -3004,7 +3004,7 @@
date = opts.get('date')
if date:
- opts['date'] = util.parsedate(date)
+ opts['date'] = dateutil.parsedate(date)
exact = opts.get('exact')
update = not opts.get('bypass')
@@ -5330,7 +5330,7 @@
date = opts.get('date')
if date:
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
if opts.get('remove'):
editform = 'tag.remove'
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3118,7 +3118,7 @@
'''commit the specified files or all outstanding changes'''
date = opts.get('date')
if date:
- opts['date'] = util.parsedate(date)
+ opts['date'] = dateutil.parsedate(date)
message = logmessage(ui, opts)
matcher = scmutil.match(repo[None], pats, opts)
@@ -3183,7 +3183,7 @@
date = opts.get('date') or old.date()
# Parse the date to allow comparison between date and old.date()
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
if len(old.parents()) > 1:
# ctx.files() isn't reliable for merges, so fall back to the
diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -512,7 +512,7 @@
desc = stripdesc(desc)
if date:
- parseddate = "%d %d" % util.parsedate(date)
+ parseddate = "%d %d" % dateutil.parsedate(date)
else:
parseddate = "%d %d" % dateutil.makedate()
if extra:
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -663,7 +663,7 @@
# start
if date:
- start_time = util.parsedate(date)
+ start_time = dateutil.parsedate(date)
else:
start_time = dateutil.makedate()
diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -1200,7 +1200,7 @@
user = opts.get('user')
date = opts.get('date')
if date:
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
diffopts = self.diffopts({'git': opts.get('git')}, plain=True)
if opts.get('checkname', True):
self.checkpatchname(patchfn)
@@ -1646,7 +1646,7 @@
newuser = opts.get('user')
newdate = opts.get('date')
if newdate:
- newdate = '%d %d' % util.parsedate(newdate)
+ newdate = '%d %d' % dateutil.parsedate(newdate)
wlock = repo.wlock()
try:
diff --git a/hgext/keyword.py b/hgext/keyword.py
--- a/hgext/keyword.py
+++ b/hgext/keyword.py
@@ -156,7 +156,8 @@
def utcdate(text):
'''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".
'''
- return dateutil.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S')
+ dateformat = '%Y/%m/%d %H:%M:%S'
+ return dateutil.datestr((dateutil.parsedate(text)[0], 0), dateformat)
# date like in svn's $Date
@templatefilter('svnisodate')
def svnisodate(text):
@@ -170,7 +171,8 @@
'''Date. Returns a UTC-date in this format: "2009-08-18
11:00:13Z".
'''
- return dateutil.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ')
+ dateformat = '%Y-%m-%d %H:%M:%SZ'
+ return dateutil.datestr((dateutil.parsedate(text)[0], 0), dateformat)
# make keyword tools accessible
kwtools = {'hgcmd': ''}
diff --git a/hgext/gpg.py b/hgext/gpg.py
--- a/hgext/gpg.py
+++ b/hgext/gpg.py
@@ -21,6 +21,7 @@
registrar,
util,
)
+from mercurial.utils import dateutil
cmdtable = {}
command = registrar.command(cmdtable)
@@ -259,7 +260,7 @@
date = opts.get('date')
if date:
- opts['date'] = util.parsedate(date)
+ opts['date'] = dateutil.parsedate(date)
if revs:
nodes = [repo.lookup(n) for n in revs]
diff --git a/hgext/fetch.py b/hgext/fetch.py
--- a/hgext/fetch.py
+++ b/hgext/fetch.py
@@ -23,6 +23,7 @@
registrar,
util,
)
+from mercurial.utils import dateutil
release = lock.release
cmdtable = {}
@@ -64,7 +65,7 @@
opts = pycompat.byteskwargs(opts)
date = opts.get('date')
if date:
- opts['date'] = util.parsedate(date)
+ opts['date'] = dateutil.parsedate(date)
parent, _p2 = repo.dirstate.parents()
branch = repo.dirstate.branch()
diff --git a/hgext/convert/subversion.py b/hgext/convert/subversion.py
--- a/hgext/convert/subversion.py
+++ b/hgext/convert/subversion.py
@@ -891,7 +891,7 @@
# Example SVN datetime. Includes microseconds.
# ISO-8601 conformant
# '2007-01-04T17:35:00.902377Z'
- date = util.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"])
+ date = dateutil.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"])
if self.ui.configbool('convert', 'localtimezone'):
date = makedatetimestamp(date[0])
diff --git a/hgext/convert/cvsps.py b/hgext/convert/cvsps.py
--- a/hgext/convert/cvsps.py
+++ b/hgext/convert/cvsps.py
@@ -337,7 +337,7 @@
if len(d.split()) != 3:
# cvs log dates always in GMT
d = d + ' UTC'
- e.date = util.parsedate(d, ['%y/%m/%d %H:%M:%S',
+ e.date = dateutil.parsedate(d, ['%y/%m/%d %H:%M:%S',
'%Y/%m/%d %H:%M:%S',
'%Y-%m-%d %H:%M:%S'])
e.author = scache(match.group(2))
diff --git a/hgext/convert/convcmd.py b/hgext/convert/convcmd.py
--- a/hgext/convert/convcmd.py
+++ b/hgext/convert/convcmd.py
@@ -19,6 +19,7 @@
scmutil,
util,
)
+from mercurial.utils import dateutil
from . import (
bzr,
@@ -356,7 +357,7 @@
dates = {}
def getdate(n):
if n not in dates:
- dates[n] = util.parsedate(self.commitcache[n].date)
+ dates[n] = dateutil.parsedate(self.commitcache[n].date)
return dates[n]
def picknext(nodes):
To: lothiraldan, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list