--- a/contrib/synthrepo.py Thu Feb 08 23:27:24 2018 +0530
+++ b/contrib/synthrepo.py Thu Feb 15 17:18:26 2018 +0100
@@ -59,8 +59,8 @@
patch,
registrar,
scmutil,
- util,
)
+from mercurial.utils import dateutil
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
@@ -382,7 +382,7 @@
message = 'synthesized wide repo with %d files' % (len(files),)
mc = context.memctx(repo, [pctx.node(), nullid], message,
files, filectxfn, ui.username(),
- '%d %d' % util.makedate())
+ '%d %d' % dateutil.makedate())
initnode = mc.commit()
if ui.debugflag:
hexfn = hex
--- a/hgext/blackbox.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/blackbox.py Thu Feb 15 17:18:26 2018 +0100
@@ -49,6 +49,7 @@
ui as uimod,
util,
)
+from mercurial.utils import dateutil
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
@@ -164,7 +165,7 @@
return
ui._bbinlog = True
default = self.configdate('devel', 'default-date')
- date = util.datestr(default, '%Y/%m/%d %H:%M:%S')
+ date = dateutil.datestr(default, '%Y/%m/%d %H:%M:%S')
user = util.getuser()
pid = '%d' % util.getpid()
formattedmsg = msg[0] % msg[1:]
--- a/hgext/churn.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/churn.py Thu Feb 15 17:18:26 2018 +0100
@@ -23,8 +23,8 @@
pycompat,
registrar,
scmutil,
- util,
)
+from mercurial.utils import dateutil
cmdtable = {}
command = registrar.command(cmdtable)
@@ -65,7 +65,7 @@
rate = {}
df = False
if opts.get('date'):
- df = util.matchdate(opts['date'])
+ df = dateutil.matchdate(opts['date'])
m = scmutil.match(repo[None], pats, opts)
def prep(ctx, fns):
--- a/hgext/convert/common.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/common.py Thu Feb 15 17:18:26 2018 +0100
@@ -541,7 +541,7 @@
self.fp = None
def makedatetimestamp(t):
- """Like util.makedate() but for time t instead of current time"""
+ """Like dateutil.makedate() but for time t instead of current time"""
delta = (datetime.datetime.utcfromtimestamp(t) -
datetime.datetime.fromtimestamp(t))
tz = delta.days * 86400 + delta.seconds
--- a/hgext/convert/convcmd.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/convcmd.py Thu Feb 15 17:18:26 2018 +0100
@@ -19,6 +19,7 @@
scmutil,
util,
)
+from mercurial.utils import dateutil
from . import (
bzr,
@@ -355,7 +356,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):
--- a/hgext/convert/cvs.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/cvs.py Thu Feb 15 17:18:26 2018 +0100
@@ -18,6 +18,7 @@
pycompat,
util,
)
+from mercurial.utils import dateutil
from . import (
common,
@@ -93,7 +94,7 @@
cs.comment = self.recode(cs.comment)
if self.ui.configbool('convert', 'localtimezone'):
cs.date = makedatetimestamp(cs.date[0])
- date = util.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2')
+ date = dateutil.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2')
self.tags.update(dict.fromkeys(cs.tags, id))
files = {}
--- a/hgext/convert/cvsps.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/cvsps.py Thu Feb 15 17:18:26 2018 +0100
@@ -17,6 +17,7 @@
pycompat,
util,
)
+from mercurial.utils import dateutil
pickle = util.pickle
@@ -192,7 +193,7 @@
if oldlog:
date = oldlog[-1].date # last commit date as a (time,tz) tuple
- date = util.datestr(date, '%Y/%m/%d %H:%M:%S %1%2')
+ date = dateutil.datestr(date, '%Y/%m/%d %H:%M:%S %1%2')
# build the CVS commandline
cmd = ['cvs', '-q']
@@ -336,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))
@@ -901,7 +902,7 @@
# bug-for-bug compatibility with cvsps.
ui.write('---------------------\n')
ui.write(('PatchSet %d \n' % cs.id))
- ui.write(('Date: %s\n' % util.datestr(cs.date,
+ ui.write(('Date: %s\n' % dateutil.datestr(cs.date,
'%Y/%m/%d %H:%M:%S %1%2')))
ui.write(('Author: %s\n' % cs.author))
ui.write(('Branch: %s\n' % (cs.branch or 'HEAD')))
--- a/hgext/convert/darcs.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/darcs.py Thu Feb 15 17:18:26 2018 +0100
@@ -16,6 +16,7 @@
error,
util,
)
+from mercurial.utils import dateutil
from . import common
NoRepo = common.NoRepo
@@ -148,12 +149,14 @@
def getcommit(self, rev):
elt = self.changes[rev]
- date = util.strdate(elt.get('local_date'), '%a %b %d %H:%M:%S %Z %Y')
+ dateformat = '%a %b %d %H:%M:%S %Z %Y'
+ date = dateutil.strdate(elt.get('local_date'), dateformat)
desc = elt.findtext('name') + '\n' + elt.findtext('comment', '')
# etree can return unicode objects for name, comment, and author,
# so recode() is used to ensure str objects are emitted.
+ newdateformat = '%Y-%m-%d %H:%M:%S %1%2'
return common.commit(author=self.recode(elt.get('author')),
- date=util.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'),
+ date=dateutil.datestr(date, newdateformat),
desc=self.recode(desc).strip(),
parents=self.parents[rev])
--- a/hgext/convert/gnuarch.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/gnuarch.py Thu Feb 15 17:18:26 2018 +0100
@@ -19,6 +19,7 @@
error,
util,
)
+from mercurial.utils import dateutil
from . import common
class gnuarch_source(common.converter_source, common.commandline):
@@ -280,8 +281,8 @@
catlog = self.catlogparser.parsestr(data)
# Commit date
- self.changes[rev].date = util.datestr(
- util.strdate(catlog['Standard-date'],
+ self.changes[rev].date = dateutil.datestr(
+ dateutil.strdate(catlog['Standard-date'],
'%Y-%m-%d %H:%M:%S'))
# Commit author
--- a/hgext/convert/hg.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/hg.py Thu Feb 15 17:18:26 2018 +0100
@@ -36,6 +36,7 @@
scmutil,
util,
)
+from mercurial.utils import dateutil
stringio = util.stringio
from . import common
@@ -583,7 +584,7 @@
crev = rev
return common.commit(author=ctx.user(),
- date=util.datestr(ctx.date(),
+ date=dateutil.datestr(ctx.date(),
'%Y-%m-%d %H:%M:%S %1%2'),
desc=ctx.description(),
rev=crev,
--- a/hgext/convert/monotone.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/monotone.py Thu Feb 15 17:18:26 2018 +0100
@@ -14,8 +14,8 @@
from mercurial import (
error,
pycompat,
- util,
)
+from mercurial.utils import dateutil
from . import common
@@ -310,9 +310,10 @@
certs = self.mtngetcerts(rev)
if certs.get('suspend') == certs["branch"]:
extra['close'] = 1
+ dateformat = "%Y-%m-%dT%H:%M:%S"
return common.commit(
author=certs["author"],
- date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")),
+ date=dateutil.datestr(dateutil.strdate(certs["date"], dateformat)),
desc=certs["changelog"],
rev=rev,
parents=self.mtnrun("parents", rev).splitlines(),
--- a/hgext/convert/p4.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/p4.py Thu Feb 15 17:18:26 2018 +0100
@@ -14,6 +14,7 @@
error,
util,
)
+from mercurial.utils import dateutil
from . import common
@@ -346,7 +347,7 @@
parents = []
return common.commit(author=self.recode(obj["user"]),
- date=util.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'),
+ date=dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'),
parents=parents, desc=desc, branch=None, rev=obj['change'],
extra={"p4": obj['change'], "convert_revision": obj['change']})
--- a/hgext/convert/subversion.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/convert/subversion.py Thu Feb 15 17:18:26 2018 +0100
@@ -16,6 +16,7 @@
util,
vfs as vfsmod,
)
+from mercurial.utils import dateutil
from . import common
@@ -891,7 +892,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])
@@ -913,7 +914,7 @@
branch = None
cset = commit(author=author,
- date=util.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'),
+ date=dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'),
desc=log,
parents=parents,
branch=branch,
--- a/hgext/fetch.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/fetch.py Thu Feb 15 17:18:26 2018 +0100
@@ -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()
--- a/hgext/gpg.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/gpg.py Thu Feb 15 17:18:26 2018 +0100
@@ -21,6 +21,7 @@
registrar,
util,
)
+from mercurial.utils import dateutil
cmdtable = {}
command = registrar.command(cmdtable)
@@ -258,7 +259,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]
--- a/hgext/journal.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/journal.py Thu Feb 15 17:18:26 2018 +0100
@@ -35,6 +35,7 @@
registrar,
util,
)
+from mercurial.utils import dateutil
cmdtable = {}
command = registrar.command(cmdtable)
@@ -326,7 +327,7 @@
newhashes = [newhashes]
entry = journalentry(
- util.makedate(), self.user, self.command, namespace, name,
+ dateutil.makedate(), self.user, self.command, namespace, name,
oldhashes, newhashes)
vfs = self.vfs
--- a/hgext/keyword.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/keyword.py Thu Feb 15 17:18:26 2018 +0100
@@ -111,6 +111,7 @@
templatefilters,
util,
)
+from mercurial.utils import dateutil
cmdtable = {}
command = registrar.command(cmdtable)
@@ -156,21 +157,23 @@
def utcdate(text):
'''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".
'''
- return util.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):
'''Date. Returns a date in this format: "2009-08-18 13:00:13
+0200 (Tue, 18 Aug 2009)".
'''
- return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
+ return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
# date like in svn's $Id
@templatefilter('svnutcdate')
def svnutcdate(text):
'''Date. Returns a UTC-date in this format: "2009-08-18
11:00:13Z".
'''
- return util.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': ''}
--- a/hgext/mq.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/mq.py Thu Feb 15 17:18:26 2018 +0100
@@ -98,6 +98,7 @@
util,
vfs as vfsmod,
)
+from mercurial.utils import dateutil
release = lockmod.release
seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
@@ -1201,7 +1202,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)
@@ -1644,7 +1645,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:
@@ -2596,7 +2597,7 @@
if not opts.get('user') and opts.get('currentuser'):
opts['user'] = ui.username()
if not opts.get('date') and opts.get('currentdate'):
- opts['date'] = "%d %d" % util.makedate()
+ opts['date'] = "%d %d" % dateutil.makedate()
@command("^qnew",
[('e', 'edit', None, _('invoke editor on commit messages')),
--- a/hgext/notify.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/notify.py Thu Feb 15 17:18:26 2018 +0100
@@ -149,6 +149,7 @@
registrar,
util,
)
+from mercurial.utils import dateutil
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
@@ -360,7 +361,7 @@
for k, v in headers:
msg[k] = v
- msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2")
+ msg['Date'] = dateutil.datestr(format="%a, %d %b %Y %H:%M:%S %1%2")
# try to make subject line exist and be useful
if not subject:
--- a/hgext/patchbomb.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/patchbomb.py Thu Feb 15 17:18:26 2018 +0100
@@ -99,6 +99,7 @@
templater,
util,
)
+from mercurial.utils import dateutil
stringio = util.stringio
cmdtable = {}
@@ -665,9 +666,9 @@
# start
if date:
- start_time = util.parsedate(date)
+ start_time = dateutil.parsedate(date)
else:
- start_time = util.makedate()
+ start_time = dateutil.makedate()
def genmsgid(id):
return '<%s.%d@%s>' % (id[:20], int(start_time[0]),
--- a/hgext/shelve.py Thu Feb 08 23:27:24 2018 +0530
+++ b/hgext/shelve.py Thu Feb 15 17:18:26 2018 +0100
@@ -55,6 +55,7 @@
from . import (
rebase,
)
+from mercurial.utils import dateutil
cmdtable = {}
command = registrar.command(cmdtable)
@@ -563,7 +564,8 @@
continue
ui.write(' ' * (16 - len(sname)))
used = 16
- age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
+ date = dateutil.makedate(mtime)
+ age = '(%s)' % templatefilters.age(date, abbrev=True)
ui.write(age, label='shelve.age')
ui.write(' ' * (12 - len(age)))
used += 12
--- a/mercurial/changelog.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/changelog.py Thu Feb 15 17:18:26 2018 +0100
@@ -24,6 +24,7 @@
revlog,
util,
)
+from .utils import dateutil
_defaultextra = {'branch': 'default'}
@@ -524,9 +525,9 @@
desc = stripdesc(desc)
if date:
- parseddate = "%d %d" % util.parsedate(date)
+ parseddate = "%d %d" % dateutil.parsedate(date)
else:
- parseddate = "%d %d" % util.makedate()
+ parseddate = "%d %d" % dateutil.makedate()
if extra:
branch = extra.get("branch")
if branch in ("default", ""):
--- a/mercurial/cmdutil.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/cmdutil.py Thu Feb 15 17:18:26 2018 +0100
@@ -47,6 +47,7 @@
util,
vfs as vfsmod,
)
+from .utils import dateutil
stringio = util.stringio
# templates of common command options
@@ -1530,7 +1531,7 @@
write("# HG changeset patch\n")
write("# User %s\n" % ctx.user())
write("# Date %d %d\n" % ctx.date())
- write("# %s\n" % util.datestr(ctx.date()))
+ write("# %s\n" % dateutil.datestr(ctx.date()))
if branch and branch != 'default':
write("# Branch %s\n" % branch)
write("# Node ID %s\n" % hex(node))
@@ -1629,7 +1630,7 @@
def finddate(ui, repo, date):
"""Find the tipmost changeset that matches the given date spec"""
- df = util.matchdate(date)
+ df = dateutil.matchdate(date)
m = scmutil.matchall(repo)
results = {}
@@ -1642,7 +1643,7 @@
rev = ctx.rev()
if rev in results:
ui.status(_("found revision %s from %s\n") %
- (rev, util.datestr(results[rev])))
+ (rev, dateutil.datestr(results[rev])))
return '%d' % rev
raise error.Abort(_("revision matching date not found"))
@@ -2261,7 +2262,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)
@@ -2326,7 +2327,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
--- a/mercurial/commands.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/commands.py Thu Feb 15 17:18:26 2018 +0100
@@ -61,6 +61,7 @@
util,
wireprotoserver,
)
+from .utils import dateutil
release = lockmod.release
@@ -302,9 +303,9 @@
rootfm = ui.formatter('annotate', opts)
if ui.quiet:
- datefunc = util.shortdate
+ datefunc = dateutil.shortdate
else:
- datefunc = util.datestr
+ datefunc = dateutil.datestr
if ctx.rev() is None:
def hexfn(node):
if node is None:
@@ -584,7 +585,7 @@
date = opts.get('date')
if date:
- opts['date'] = util.parsedate(date)
+ opts['date'] = dateutil.parsedate(date)
cmdutil.checkunfinished(repo)
cmdutil.bailifchanged(repo)
@@ -2161,7 +2162,7 @@
if not opts.get('user') and opts.get('currentuser'):
opts['user'] = ui.username()
if not opts.get('date') and opts.get('currentdate'):
- opts['date'] = "%d %d" % util.makedate()
+ opts['date'] = "%d %d" % dateutil.makedate()
editor = cmdutil.getcommiteditor(editform='graft',
**pycompat.strkwargs(opts))
@@ -3011,7 +3012,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')
@@ -5307,7 +5308,7 @@
date = opts.get('date')
if date:
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
if opts.get('remove'):
editform = 'tag.remove'
--- a/mercurial/context.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/context.py Thu Feb 15 17:18:26 2018 +0100
@@ -49,6 +49,7 @@
subrepoutil,
util,
)
+from .utils import dateutil
propertycache = util.propertycache
@@ -1287,7 +1288,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:
@@ -1364,7 +1365,7 @@
ui = self._repo.ui
date = ui.configdate('devel', 'default-date')
if date is None:
- date = util.makedate()
+ date = dateutil.makedate()
return date
def subrev(self, subpath):
@@ -2111,11 +2112,11 @@
if data is None:
raise error.ProgrammingError("data must be non-None")
self._auditconflicts(path)
- self._markdirty(path, exists=True, data=data, date=util.makedate(),
+ self._markdirty(path, exists=True, data=data, date=dateutil.makedate(),
flags=flags)
def setflags(self, path, l, x):
- self._markdirty(path, exists=True, date=util.makedate(),
+ self._markdirty(path, exists=True, date=dateutil.makedate(),
flags=(l and 'l' or '') + (x and 'x' or ''))
def remove(self, path):
@@ -2404,7 +2405,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.
"""
@@ -2619,7 +2620,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):
--- a/mercurial/debugcommands.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/debugcommands.py Thu Feb 15 17:18:26 2018 +0100
@@ -77,6 +77,7 @@
vfs as vfsmod,
wireprotoserver,
)
+from .utils import dateutil
release = lockmod.release
@@ -560,13 +561,13 @@
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: %d %d\n") % d)
- ui.write(("standard: %s\n") % util.datestr(d))
+ ui.write(("standard: %s\n") % dateutil.datestr(d))
if range:
- m = util.matchdate(range)
+ m = dateutil.matchdate(range)
ui.write(("match: %s\n") % m(d[0]))
@command('debugdeltachain',
@@ -1578,7 +1579,7 @@
try:
date = opts.get('date')
if date:
- date = util.parsedate(date)
+ date = dateutil.parsedate(date)
else:
date = None
prec = parsenodeid(precursor)
--- a/mercurial/formatter.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/formatter.py Thu Feb 15 17:18:26 2018 +0100
@@ -126,6 +126,7 @@
templater,
util,
)
+from .utils import dateutil
pickle = util.pickle
@@ -243,7 +244,7 @@
@staticmethod
def formatdate(date, fmt):
'''stringify date tuple in the given format'''
- return util.datestr(date, fmt)
+ return dateutil.datestr(date, fmt)
@staticmethod
def formatdict(data, key, value, fmt, sep):
'''stringify key-value pairs separated by sep'''
--- a/mercurial/hgweb/hgwebdir_mod.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/hgweb/hgwebdir_mod.py Thu Feb 15 17:18:26 2018 +0100
@@ -46,6 +46,7 @@
webutil,
wsgicgi,
)
+from ..utils import dateutil
def cleannames(items):
return [(util.pconvert(name).strip('/'), path) for name, path in items]
@@ -376,7 +377,7 @@
if directory:
# get the directory's time information
try:
- d = (get_mtime(path), util.makedate()[1])
+ d = (get_mtime(path), dateutil.makedate()[1])
except OSError:
continue
@@ -425,7 +426,7 @@
u.warn(_('error accessing repository at %s\n') % path)
continue
try:
- d = (get_mtime(r.spath), util.makedate()[1])
+ d = (get_mtime(r.spath), dateutil.makedate()[1])
except OSError:
continue
--- a/mercurial/logcmdutil.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/logcmdutil.py Thu Feb 15 17:18:26 2018 +0100
@@ -35,6 +35,7 @@
templater,
util,
)
+from .utils import dateutil
def getlimit(opts):
"""get the log limit according to option -l/--limit"""
@@ -229,7 +230,7 @@
% scmutil.formatrevnode(self.ui, mrev, mnode),
label='ui.debug log.manifest')
self.ui.write(columns['user'] % ctx.user(), label='log.user')
- self.ui.write(columns['date'] % util.datestr(ctx.date()),
+ self.ui.write(columns['date'] % dateutil.datestr(ctx.date()),
label='log.date')
if ctx.isunstable():
--- a/mercurial/mdiff.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/mdiff.py Thu Feb 15 17:18:26 2018 +0100
@@ -19,6 +19,7 @@
pycompat,
util,
)
+from .utils import dateutil
_missing_newline_marker = "\\ No newline at end of file\n"
@@ -255,7 +256,7 @@
aprefix = 'a/'
bprefix = 'b/'
- epoch = util.datestr((0, 0))
+ epoch = dateutil.datestr((0, 0))
fn1 = util.pconvert(fn1)
fn2 = util.pconvert(fn2)
--- a/mercurial/obsolete.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/obsolete.py Thu Feb 15 17:18:26 2018 +0100
@@ -81,6 +81,7 @@
policy,
util,
)
+from .utils import dateutil
parsers = policy.importmod(r'parsers')
@@ -601,13 +602,13 @@
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:
- date = util.makedate()
+ date = dateutil.makedate()
else:
- date = util.makedate()
+ date = dateutil.makedate()
if len(prec) != 20:
raise ValueError(prec)
for succ in succs:
--- a/mercurial/obsutil.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/obsutil.py Thu Feb 15 17:18:26 2018 +0100
@@ -15,6 +15,7 @@
phases,
util,
)
+from .utils import dateutil
class marker(object):
"""Wrap obsolete marker raw data"""
@@ -841,11 +842,11 @@
max_date = max(dates)
if min_date == max_date:
- fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
+ fmtmin_date = dateutil.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
line.append(" (at %s)" % fmtmin_date)
else:
- fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
- fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M %1%2')
+ fmtmin_date = dateutil.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
+ fmtmax_date = dateutil.datestr(max_date, '%Y-%m-%d %H:%M %1%2')
line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date))
return "".join(line)
--- a/mercurial/patch.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/patch.py Thu Feb 15 17:18:26 2018 +0100
@@ -40,6 +40,7 @@
util,
vfs as vfsmod,
)
+from .utils import dateutil
diffhelpers = policy.importmod(r'diffhelpers')
stringio = util.stringio
@@ -2669,8 +2670,8 @@
def isempty(fctx):
return fctx is None or fctx.size() == 0
- date1 = util.datestr(ctx1.date())
- date2 = util.datestr(ctx2.date())
+ date1 = dateutil.datestr(ctx1.date())
+ date2 = dateutil.datestr(ctx2.date())
gitmode = {'l': '120000', 'x': '100755', '': '100644'}
--- a/mercurial/revset.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/revset.py Thu Feb 15 17:18:26 2018 +0100
@@ -30,6 +30,7 @@
smartset,
util,
)
+from .utils import dateutil
# helpers for processing parsed tree
getsymbol = revsetlang.getsymbol
@@ -658,7 +659,7 @@
"""
# i18n: "date" is a keyword
ds = getstring(x, _("date requires a string"))
- dm = util.matchdate(ds)
+ dm = dateutil.matchdate(ds)
return subset.filter(lambda x: dm(repo[x].date()[0]),
condrepr=('<date %r>', ds))
--- a/mercurial/subrepo.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/subrepo.py Thu Feb 15 17:18:26 2018 +0100
@@ -36,6 +36,7 @@
util,
vfs as vfsmod,
)
+from .utils import dateutil
hg = None
reporelpath = subrepoutil.reporelpath
@@ -1467,7 +1468,7 @@
if date:
# git's date parser silently ignores when seconds < 1e9
# convert to ISO8601
- env['GIT_AUTHOR_DATE'] = util.datestr(date,
+ env['GIT_AUTHOR_DATE'] = dateutil.datestr(date,
'%Y-%m-%dT%H:%M:%S %1%2')
self._gitcommand(cmd, env=env)
# make sure commit works otherwise HEAD might not exist under certain
--- a/mercurial/templatefilters.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/templatefilters.py Thu Feb 15 17:18:26 2018 +0100
@@ -22,6 +22,7 @@
url,
util,
)
+from .utils import dateutil
urlerr = util.urlerr
urlreq = util.urlreq
@@ -78,7 +79,7 @@
else:
delta = max(1, int(now - then))
if delta > agescales[0][1] * 2:
- return util.shortdate(date)
+ return dateutil.shortdate(date)
for t, s, a in agescales:
n = delta // s
@@ -203,7 +204,7 @@
"""Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
+0200".
"""
- return util.datestr(text, '%Y-%m-%d %H:%M %1%2')
+ return dateutil.datestr(text, '%Y-%m-%d %H:%M %1%2')
@templatefilter('isodatesec')
def isodatesec(text):
@@ -211,7 +212,7 @@
seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
filter.
"""
- return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
+ return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
def indent(text, prefix):
'''indent each non-empty line of text after first with prefix.'''
@@ -325,14 +326,14 @@
"""Date. Returns a date using the Internet date format
specified in RFC 3339: "2009-08-18T13:00:13+02:00".
"""
- return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
+ return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
@templatefilter('rfc822date')
def rfc822date(text):
"""Date. Returns a date using the same format used in email
headers: "Tue, 18 Aug 2009 13:00:13 +0200".
"""
- return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
+ return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
@templatefilter('short')
def short(text):
@@ -353,7 +354,7 @@
@templatefilter('shortdate')
def shortdate(text):
"""Date. Returns a date like "2006-09-18"."""
- return util.shortdate(text)
+ return dateutil.shortdate(text)
@templatefilter('slashpath')
def slashpath(path):
--- a/mercurial/templater.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/templater.py Thu Feb 15 17:18:26 2018 +0100
@@ -29,6 +29,7 @@
templatekw,
util,
)
+from .utils import dateutil
class ResourceUnavailable(error.Abort):
pass
@@ -649,9 +650,9 @@
fmt = evalstring(context, mapping, args[1])
try:
if fmt is None:
- return util.datestr(date)
+ return dateutil.datestr(date)
else:
- return util.datestr(date, fmt)
+ return dateutil.datestr(date, fmt)
except (TypeError, ValueError):
# i18n: "date" is a keyword
raise error.ParseError(_("date expects a date information"))
@@ -954,7 +955,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"))
@@ -962,7 +963,7 @@
tzoffset = None
tz = evalfuncarg(context, mapping, args[1])
if isinstance(tz, bytes):
- tzoffset, remainder = util.parsetimezone(tz)
+ tzoffset, remainder = dateutil.parsetimezone(tz)
if remainder:
tzoffset = None
if tzoffset is None:
@@ -972,7 +973,7 @@
# i18n: "localdate" is a keyword
raise error.ParseError(_("localdate expects a timezone"))
else:
- tzoffset = util.makedate()[1]
+ tzoffset = dateutil.makedate()[1]
return (date[0], tzoffset)
@templatefunc('max(iterable)')
--- a/mercurial/ui.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/ui.py Thu Feb 15 17:18:26 2018 +0100
@@ -37,6 +37,7 @@
scmutil,
util,
)
+from .utils import dateutil
urlreq = util.urlreq
@@ -714,7 +715,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
--- a/mercurial/util.py Thu Feb 08 23:27:24 2018 +0530
+++ b/mercurial/util.py Thu Feb 15 17:18:26 2018 +0100
@@ -17,11 +17,9 @@
import abc
import bz2
-import calendar
import codecs
import collections
import contextlib
-import datetime
import errno
import gc
import hashlib
@@ -55,6 +53,7 @@
pycompat,
urllibcompat,
)
+from .utils import dateutil
base85 = policy.importmod(r'base85')
osutil = policy.importmod(r'osutil')
@@ -855,48 +854,6 @@
if n == 4:
return (vints[0], vints[1], vints[2], extra)
-# used by parsedate
-defaultdateformats = (
- '%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601
- '%Y-%m-%dT%H:%M', # without seconds
- '%Y-%m-%dT%H%M%S', # another awful but legal variant without :
- '%Y-%m-%dT%H%M', # without seconds
- '%Y-%m-%d %H:%M:%S', # our common legal variant
- '%Y-%m-%d %H:%M', # without seconds
- '%Y-%m-%d %H%M%S', # without :
- '%Y-%m-%d %H%M', # without seconds
- '%Y-%m-%d %I:%M:%S%p',
- '%Y-%m-%d %H:%M',
- '%Y-%m-%d %I:%M%p',
- '%Y-%m-%d',
- '%m-%d',
- '%m/%d',
- '%m/%d/%y',
- '%m/%d/%Y',
- '%a %b %d %H:%M:%S %Y',
- '%a %b %d %I:%M:%S%p %Y',
- '%a, %d %b %Y %H:%M:%S', # GNU coreutils "/bin/date --rfc-2822"
- '%b %d %H:%M:%S %Y',
- '%b %d %I:%M:%S%p %Y',
- '%b %d %H:%M:%S',
- '%b %d %I:%M:%S%p',
- '%b %d %H:%M',
- '%b %d %I:%M%p',
- '%b %d %Y',
- '%b %d',
- '%H:%M:%S',
- '%I:%M:%S%p',
- '%H:%M',
- '%I:%M%p',
-)
-
-extendeddateformats = defaultdateformats + (
- "%Y",
- "%Y-%m",
- "%b",
- "%b %Y",
- )
-
def cachefunc(func):
'''cache the result of function calls'''
# XXX doesn't handle keywords args
@@ -2304,277 +2261,6 @@
return data
-def makedate(timestamp=None):
- '''Return a unix timestamp (or the current time) as a (unixtime,
- offset) tuple based off the local timezone.'''
- if timestamp is None:
- timestamp = time.time()
- if timestamp < 0:
- hint = _("check your clock")
- raise Abort(_("negative timestamp: %d") % timestamp, hint=hint)
- delta = (datetime.datetime.utcfromtimestamp(timestamp) -
- datetime.datetime.fromtimestamp(timestamp))
- tz = delta.days * 86400 + delta.seconds
- return timestamp, tz
-
-def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'):
- """represent a (unixtime, offset) tuple as a localized time.
- unixtime is seconds since the epoch, and offset is the time zone's
- number of seconds away from UTC.
-
- >>> datestr((0, 0))
- 'Thu Jan 01 00:00:00 1970 +0000'
- >>> datestr((42, 0))
- 'Thu Jan 01 00:00:42 1970 +0000'
- >>> datestr((-42, 0))
- 'Wed Dec 31 23:59:18 1969 +0000'
- >>> datestr((0x7fffffff, 0))
- 'Tue Jan 19 03:14:07 2038 +0000'
- >>> datestr((-0x80000000, 0))
- 'Fri Dec 13 20:45:52 1901 +0000'
- """
- t, tz = date or makedate()
- if "%1" in format or "%2" in format or "%z" in format:
- sign = (tz > 0) and "-" or "+"
- minutes = abs(tz) // 60
- q, r = divmod(minutes, 60)
- format = format.replace("%z", "%1%2")
- format = format.replace("%1", "%c%02d" % (sign, q))
- format = format.replace("%2", "%02d" % r)
- d = t - tz
- if d > 0x7fffffff:
- d = 0x7fffffff
- elif d < -0x80000000:
- d = -0x80000000
- # Never use time.gmtime() and datetime.datetime.fromtimestamp()
- # because they use the gmtime() system call which is buggy on Windows
- # for negative values.
- t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d)
- s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format)))
- return s
-
-def shortdate(date=None):
- """turn (timestamp, tzoff) tuple into iso 8631 date."""
- return datestr(date, format='%Y-%m-%d')
-
-def parsetimezone(s):
- """find a trailing timezone, if any, in string, and return a
- (offset, remainder) pair"""
- s = pycompat.bytestr(s)
-
- if s.endswith("GMT") or s.endswith("UTC"):
- return 0, s[:-3].rstrip()
-
- # Unix-style timezones [+-]hhmm
- if len(s) >= 5 and s[-5] in "+-" and s[-4:].isdigit():
- sign = (s[-5] == "+") and 1 or -1
- hours = int(s[-4:-2])
- minutes = int(s[-2:])
- return -sign * (hours * 60 + minutes) * 60, s[:-5].rstrip()
-
- # ISO8601 trailing Z
- if s.endswith("Z") and s[-2:-1].isdigit():
- return 0, s[:-1]
-
- # ISO8601-style [+-]hh:mm
- if (len(s) >= 6 and s[-6] in "+-" and s[-3] == ":" and
- s[-5:-3].isdigit() and s[-2:].isdigit()):
- sign = (s[-6] == "+") and 1 or -1
- hours = int(s[-5:-3])
- minutes = int(s[-2:])
- return -sign * (hours * 60 + minutes) * 60, s[:-6]
-
- return None, s
-
-def strdate(string, format, defaults=None):
- """parse a localized time string and return a (unixtime, offset) tuple.
- if the string cannot be parsed, ValueError is raised."""
- if defaults is None:
- defaults = {}
-
- # NOTE: unixtime = localunixtime + offset
- offset, date = parsetimezone(string)
-
- # add missing elements from defaults
- usenow = False # default to using biased defaults
- for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity
- part = pycompat.bytestr(part)
- found = [True for p in part if ("%"+p) in format]
- if not found:
- date += "@" + defaults[part][usenow]
- format += "@%" + part[0]
- else:
- # We've found a specific time element, less specific time
- # elements are relative to today
- usenow = True
-
- timetuple = time.strptime(encoding.strfromlocal(date),
- encoding.strfromlocal(format))
- localunixtime = int(calendar.timegm(timetuple))
- if offset is None:
- # local timezone
- unixtime = int(time.mktime(timetuple))
- offset = unixtime - localunixtime
- else:
- 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') % pycompat.bytestr(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
-
- Formats include:
-
- '{date}' match a given date to the accuracy provided
-
- '<{date}' on or before a given date
-
- '>{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")
- >>> f = matchdate(b"10:30")
- >>> f(p1[0])
- False
- >>> f(p2[0])
- True
- >>> f(p3[0])
- True
- >>> f(p4[0])
- False
- >>> f(p5[0])
- False
- """
-
- def lower(date):
- d = {'mb': "1", 'd': "1"}
- return 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]
- except error.ParseError:
- pass
- d["d"] = "28"
- return parsedate(date, extendeddateformats, d)[0]
-
- date = date.strip()
-
- if not date:
- raise Abort(_("dates cannot consist entirely of whitespace"))
- elif date[0] == "<":
- if not date[1:]:
- raise Abort(_("invalid day spec, use '<DATE'"))
- when = upper(date[1:])
- return lambda x: x <= when
- elif date[0] == ">":
- if not date[1:]:
- raise Abort(_("invalid day spec, use '>DATE'"))
- when = lower(date[1:])
- return lambda x: x >= when
- elif date[0] == "-":
- try:
- days = int(date[1:])
- except ValueError:
- raise Abort(_("invalid day spec: %s") % date[1:])
- if days < 0:
- raise Abort(_("%s must be nonnegative (see 'hg help dates')")
- % date[1:])
- when = makedate()[0] - days * 3600 * 24
- return lambda x: x >= when
- elif " to " in date:
- a, b = date.split(" to ")
- start, stop = lower(a), upper(b)
- return lambda x: x >= start and x <= stop
- else:
- start, stop = lower(date), upper(date)
- return lambda x: x >= start and x <= stop
-
def stringmatcher(pattern, casesensitive=True):
"""
accepts a string, possibly starting with 're:' or 'literal:' prefix.
@@ -4303,3 +3989,54 @@
if not (byte & 0x80):
return result
shift += 7
+
+###
+# Deprecation warnings for util.py splitting
+###
+
+defaultdateformats = dateutil.defaultdateformats
+
+extendeddateformats = dateutil.extendeddateformats
+
+def makedate(*args, **kwargs):
+ msg = ("'util.makedate' is deprecated, "
+ "use 'utils.dateutil.makedate'")
+ nouideprecwarn(msg, "4.6")
+ return dateutil.makedate(*args, **kwargs)
+
+def datestr(*args, **kwargs):
+ msg = ("'util.datestr' is deprecated, "
+ "use 'utils.dateutil.datestr'")
+ nouideprecwarn(msg, "4.6")
+ debugstacktrace()
+ return dateutil.datestr(*args, **kwargs)
+
+def shortdate(*args, **kwargs):
+ msg = ("'util.shortdate' is deprecated, "
+ "use 'utils.dateutil.shortdate'")
+ nouideprecwarn(msg, "4.6")
+ return dateutil.shortdate(*args, **kwargs)
+
+def parsetimezone(*args, **kwargs):
+ msg = ("'util.parsetimezone' is deprecated, "
+ "use 'utils.dateutil.parsetimezone'")
+ nouideprecwarn(msg, "4.6")
+ return dateutil.parsetimezone(*args, **kwargs)
+
+def strdate(*args, **kwargs):
+ msg = ("'util.strdate' is deprecated, "
+ "use 'utils.dateutil.strdate'")
+ 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)
+
+def matchdate(*args, **kwargs):
+ msg = ("'util.matchdate' is deprecated, "
+ "use 'utils.dateutil.matchdate'")
+ nouideprecwarn(msg, "4.6")
+ return dateutil.matchdate(*args, **kwargs)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/utils/dateutil.py Thu Feb 15 17:18:26 2018 +0100
@@ -0,0 +1,332 @@
+# util.py - Mercurial utility functions relative to dates
+#
+# Copyright 2018 Boris Feld <boris.feld@octobus.net>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import, print_function
+
+import calendar
+import datetime
+import time
+
+from ..i18n import _
+from .. import (
+ encoding,
+ error,
+ pycompat,
+)
+
+# used by parsedate
+defaultdateformats = (
+ '%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601
+ '%Y-%m-%dT%H:%M', # without seconds
+ '%Y-%m-%dT%H%M%S', # another awful but legal variant without :
+ '%Y-%m-%dT%H%M', # without seconds
+ '%Y-%m-%d %H:%M:%S', # our common legal variant
+ '%Y-%m-%d %H:%M', # without seconds
+ '%Y-%m-%d %H%M%S', # without :
+ '%Y-%m-%d %H%M', # without seconds
+ '%Y-%m-%d %I:%M:%S%p',
+ '%Y-%m-%d %H:%M',
+ '%Y-%m-%d %I:%M%p',
+ '%Y-%m-%d',
+ '%m-%d',
+ '%m/%d',
+ '%m/%d/%y',
+ '%m/%d/%Y',
+ '%a %b %d %H:%M:%S %Y',
+ '%a %b %d %I:%M:%S%p %Y',
+ '%a, %d %b %Y %H:%M:%S', # GNU coreutils "/bin/date --rfc-2822"
+ '%b %d %H:%M:%S %Y',
+ '%b %d %I:%M:%S%p %Y',
+ '%b %d %H:%M:%S',
+ '%b %d %I:%M:%S%p',
+ '%b %d %H:%M',
+ '%b %d %I:%M%p',
+ '%b %d %Y',
+ '%b %d',
+ '%H:%M:%S',
+ '%I:%M:%S%p',
+ '%H:%M',
+ '%I:%M%p',
+)
+
+extendeddateformats = defaultdateformats + (
+ "%Y",
+ "%Y-%m",
+ "%b",
+ "%b %Y",
+)
+
+def makedate(timestamp=None):
+ '''Return a unix timestamp (or the current time) as a (unixtime,
+ offset) tuple based off the local timezone.'''
+ if timestamp is None:
+ timestamp = time.time()
+ if timestamp < 0:
+ hint = _("check your clock")
+ raise error.Abort(_("negative timestamp: %d") % timestamp, hint=hint)
+ delta = (datetime.datetime.utcfromtimestamp(timestamp) -
+ datetime.datetime.fromtimestamp(timestamp))
+ tz = delta.days * 86400 + delta.seconds
+ return timestamp, tz
+
+def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'):
+ """represent a (unixtime, offset) tuple as a localized time.
+ unixtime is seconds since the epoch, and offset is the time zone's
+ number of seconds away from UTC.
+
+ >>> datestr((0, 0))
+ 'Thu Jan 01 00:00:00 1970 +0000'
+ >>> datestr((42, 0))
+ 'Thu Jan 01 00:00:42 1970 +0000'
+ >>> datestr((-42, 0))
+ 'Wed Dec 31 23:59:18 1969 +0000'
+ >>> datestr((0x7fffffff, 0))
+ 'Tue Jan 19 03:14:07 2038 +0000'
+ >>> datestr((-0x80000000, 0))
+ 'Fri Dec 13 20:45:52 1901 +0000'
+ """
+ t, tz = date or makedate()
+ if "%1" in format or "%2" in format or "%z" in format:
+ sign = (tz > 0) and "-" or "+"
+ minutes = abs(tz) // 60
+ q, r = divmod(minutes, 60)
+ format = format.replace("%z", "%1%2")
+ format = format.replace("%1", "%c%02d" % (sign, q))
+ format = format.replace("%2", "%02d" % r)
+ d = t - tz
+ if d > 0x7fffffff:
+ d = 0x7fffffff
+ elif d < -0x80000000:
+ d = -0x80000000
+ # Never use time.gmtime() and datetime.datetime.fromtimestamp()
+ # because they use the gmtime() system call which is buggy on Windows
+ # for negative values.
+ t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d)
+ s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format)))
+ return s
+
+def shortdate(date=None):
+ """turn (timestamp, tzoff) tuple into iso 8631 date."""
+ return datestr(date, format='%Y-%m-%d')
+
+def parsetimezone(s):
+ """find a trailing timezone, if any, in string, and return a
+ (offset, remainder) pair"""
+ s = pycompat.bytestr(s)
+
+ if s.endswith("GMT") or s.endswith("UTC"):
+ return 0, s[:-3].rstrip()
+
+ # Unix-style timezones [+-]hhmm
+ if len(s) >= 5 and s[-5] in "+-" and s[-4:].isdigit():
+ sign = (s[-5] == "+") and 1 or -1
+ hours = int(s[-4:-2])
+ minutes = int(s[-2:])
+ return -sign * (hours * 60 + minutes) * 60, s[:-5].rstrip()
+
+ # ISO8601 trailing Z
+ if s.endswith("Z") and s[-2:-1].isdigit():
+ return 0, s[:-1]
+
+ # ISO8601-style [+-]hh:mm
+ if (len(s) >= 6 and s[-6] in "+-" and s[-3] == ":" and
+ s[-5:-3].isdigit() and s[-2:].isdigit()):
+ sign = (s[-6] == "+") and 1 or -1
+ hours = int(s[-5:-3])
+ minutes = int(s[-2:])
+ return -sign * (hours * 60 + minutes) * 60, s[:-6]
+
+ return None, s
+
+def strdate(string, format, defaults=None):
+ """parse a localized time string and return a (unixtime, offset) tuple.
+ if the string cannot be parsed, ValueError is raised."""
+ if defaults is None:
+ defaults = {}
+
+ # NOTE: unixtime = localunixtime + offset
+ offset, date = parsetimezone(string)
+
+ # add missing elements from defaults
+ usenow = False # default to using biased defaults
+ for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity
+ part = pycompat.bytestr(part)
+ found = [True for p in part if ("%"+p) in format]
+ if not found:
+ date += "@" + defaults[part][usenow]
+ format += "@%" + part[0]
+ else:
+ # We've found a specific time element, less specific time
+ # elements are relative to today
+ usenow = True
+
+ timetuple = time.strptime(encoding.strfromlocal(date),
+ encoding.strfromlocal(format))
+ localunixtime = int(calendar.timegm(timetuple))
+ if offset is None:
+ # local timezone
+ unixtime = int(time.mktime(timetuple))
+ offset = unixtime - localunixtime
+ else:
+ 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') % pycompat.bytestr(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
+
+ Formats include:
+
+ '{date}' match a given date to the accuracy provided
+
+ '<{date}' on or before a given date
+
+ '>{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")
+ >>> f = matchdate(b"10:30")
+ >>> f(p1[0])
+ False
+ >>> f(p2[0])
+ True
+ >>> f(p3[0])
+ True
+ >>> f(p4[0])
+ False
+ >>> f(p5[0])
+ False
+ """
+
+ def lower(date):
+ d = {'mb': "1", 'd': "1"}
+ return 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]
+ except error.ParseError:
+ pass
+ d["d"] = "28"
+ return parsedate(date, extendeddateformats, d)[0]
+
+ date = date.strip()
+
+ if not date:
+ raise error.Abort(_("dates cannot consist entirely of whitespace"))
+ elif date[0] == "<":
+ if not date[1:]:
+ raise error.Abort(_("invalid day spec, use '<DATE'"))
+ when = upper(date[1:])
+ return lambda x: x <= when
+ elif date[0] == ">":
+ if not date[1:]:
+ raise error.Abort(_("invalid day spec, use '>DATE'"))
+ when = lower(date[1:])
+ return lambda x: x >= when
+ elif date[0] == "-":
+ try:
+ days = int(date[1:])
+ except ValueError:
+ raise error.Abort(_("invalid day spec: %s") % date[1:])
+ if days < 0:
+ raise error.Abort(_("%s must be nonnegative (see 'hg help dates')")
+ % date[1:])
+ when = makedate()[0] - days * 3600 * 24
+ return lambda x: x >= when
+ elif " to " in date:
+ a, b = date.split(" to ")
+ start, stop = lower(a), upper(b)
+ return lambda x: x >= start and x <= stop
+ else:
+ start, stop = lower(date), upper(date)
+ return lambda x: x >= start and x <= stop
--- a/setup.py Thu Feb 08 23:27:24 2018 +0530
+++ b/setup.py Thu Feb 15 17:18:26 2018 +0100
@@ -809,6 +809,7 @@
'mercurial.pure',
'mercurial.thirdparty',
'mercurial.thirdparty.attr',
+ 'mercurial.utils',
'hgext', 'hgext.convert', 'hgext.fsmonitor',
'hgext.fsmonitor.pywatchman', 'hgext.highlight',
'hgext.largefiles', 'hgext.lfs', 'hgext.narrow',
--- a/tests/fakedirstatewritetime.py Thu Feb 08 23:27:24 2018 +0530
+++ b/tests/fakedirstatewritetime.py Thu Feb 15 17:18:26 2018 +0100
@@ -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, [b'%Y%m%d%H%M'])[0]
+ fakenow = dateutil.parsedate(fakenow, [b'%Y%m%d%H%M'])[0]
orig_pack_dirstate = parsers.pack_dirstate
orig_dirstate_getfsnow = dirstate._getfsnow
--- a/tests/fakepatchtime.py Thu Feb 08 23:27:24 2018 +0530
+++ b/tests/fakepatchtime.py Thu Feb 15 17:18:26 2018 +0100
@@ -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, [b'%Y%m%d%H%M'])[0]
+ fakenow = dateutil.parsedate(fakenow, [b'%Y%m%d%H%M'])[0]
for f in files:
repo.wvfs.utime(f, (fakenow, fakenow))
--- a/tests/test-journal.t Thu Feb 08 23:27:24 2018 +0530
+++ b/tests/test-journal.t Thu Feb 15 17:18:26 2018 +0100
@@ -4,6 +4,7 @@
> # mock out util.getuser() and util.makedate() to supply testable values
> import os
> from mercurial import util
+ > from mercurial.utils import dateutil
> def mockgetuser():
> return 'foobar'
>
@@ -19,7 +20,7 @@
> return (time, 0)
>
> util.getuser = mockgetuser
- > util.makedate = mockmakedate
+ > dateutil.makedate = mockmakedate
> EOF
$ cat >> $HGRCPATH << EOF