Mercurial > public > mercurial-scm > hg
comparison mercurial/util.py @ 28825:87c6ad2251d8
date: reallow negative timestamp, fix for Windows buggy gmtime() (issue2513)
DVCS are very useful to store various texts (as legislation) written before
Unix epoch. Fri, 13 Dec 1901 is a nice gain over Thu, 01 Jan 1970.
Revert dd24f3e7ca9e and e1002cf9fe54, fix c208dcd0f709. Add tests.
author | Florent Gallaire <fgallaire@gmail.com> |
---|---|
date | Fri, 08 Apr 2016 14:11:03 +0200 |
parents | 6041fb8f2da8 |
children | 59dd920c0ddc |
comparison
equal
deleted
inserted
replaced
28824:9d31582dd636 | 28825:87c6ad2251d8 |
---|---|
1583 """represent a (unixtime, offset) tuple as a localized time. | 1583 """represent a (unixtime, offset) tuple as a localized time. |
1584 unixtime is seconds since the epoch, and offset is the time zone's | 1584 unixtime is seconds since the epoch, and offset is the time zone's |
1585 number of seconds away from UTC. if timezone is false, do not | 1585 number of seconds away from UTC. if timezone is false, do not |
1586 append time zone to string.""" | 1586 append time zone to string.""" |
1587 t, tz = date or makedate() | 1587 t, tz = date or makedate() |
1588 if t < 0: | |
1589 t = 0 # time.gmtime(lt) fails on Windows for lt < -43200 | |
1590 tz = 0 | |
1591 if "%1" in format or "%2" in format or "%z" in format: | 1588 if "%1" in format or "%2" in format or "%z" in format: |
1592 sign = (tz > 0) and "-" or "+" | 1589 sign = (tz > 0) and "-" or "+" |
1593 minutes = abs(tz) // 60 | 1590 minutes = abs(tz) // 60 |
1594 q, r = divmod(minutes, 60) | 1591 q, r = divmod(minutes, 60) |
1595 format = format.replace("%z", "%1%2") | 1592 format = format.replace("%z", "%1%2") |
1596 format = format.replace("%1", "%c%02d" % (sign, q)) | 1593 format = format.replace("%1", "%c%02d" % (sign, q)) |
1597 format = format.replace("%2", "%02d" % r) | 1594 format = format.replace("%2", "%02d" % r) |
1598 try: | 1595 d = t - tz |
1599 t = time.gmtime(float(t) - tz) | 1596 if d > 0x7fffffff: |
1600 except ValueError: | 1597 d = 0x7fffffff |
1601 # time was out of range | 1598 elif d < -0x7fffffff: |
1602 t = time.gmtime(sys.maxint) | 1599 d = -0x7fffffff |
1603 s = time.strftime(format, t) | 1600 # Never use time.gmtime() and datetime.datetime.fromtimestamp() |
1601 # because they use the gmtime() system call which is buggy on Windows | |
1602 # for negative values. | |
1603 t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d) | |
1604 s = t.strftime(format) | |
1604 return s | 1605 return s |
1605 | 1606 |
1606 def shortdate(date=None): | 1607 def shortdate(date=None): |
1607 """turn (timestamp, tzoff) tuple into iso 8631 date.""" | 1608 """turn (timestamp, tzoff) tuple into iso 8631 date.""" |
1608 return datestr(date, format='%Y-%m-%d') | 1609 return datestr(date, format='%Y-%m-%d') |
1719 # time zone offset. values must fit in signed 32 bits for | 1720 # time zone offset. values must fit in signed 32 bits for |
1720 # current 32-bit linux runtimes. timezones go from UTC-12 | 1721 # current 32-bit linux runtimes. timezones go from UTC-12 |
1721 # to UTC+14 | 1722 # to UTC+14 |
1722 if abs(when) > 0x7fffffff: | 1723 if abs(when) > 0x7fffffff: |
1723 raise Abort(_('date exceeds 32 bits: %d') % when) | 1724 raise Abort(_('date exceeds 32 bits: %d') % when) |
1724 if when < 0: | |
1725 raise Abort(_('negative date value: %d') % when) | |
1726 if offset < -50400 or offset > 43200: | 1725 if offset < -50400 or offset > 43200: |
1727 raise Abort(_('impossible time zone offset: %d') % offset) | 1726 raise Abort(_('impossible time zone offset: %d') % offset) |
1728 return when, offset | 1727 return when, offset |
1729 | 1728 |
1730 def matchdate(date): | 1729 def matchdate(date): |