bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
1551.12.28
by Aaron Bentley
 Move bundle timestamp code to timestamp  | 
1  | 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 | 
2  | 
#
 | 
|
3  | 
# This program is free software; you can redistribute it and/or modify
 | 
|
4  | 
# it under the terms of the GNU General Public License as published by
 | 
|
5  | 
# the Free Software Foundation; either version 2 of the License, or
 | 
|
6  | 
# (at your option) any later version.
 | 
|
7  | 
#
 | 
|
8  | 
# This program is distributed in the hope that it will be useful,
 | 
|
9  | 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|
10  | 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|
11  | 
# GNU General Public License for more details.
 | 
|
12  | 
#
 | 
|
13  | 
# You should have received a copy of the GNU General Public License
 | 
|
14  | 
# along with this program; if not, write to the Free Software
 | 
|
15  | 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|
16  | 
||
17  | 
import calendar  | 
|
18  | 
import time  | 
|
19  | 
||
| 
2425.6.2
by Martin Pool
 Make timestamps use existing format_date; document that function more  | 
20  | 
from bzrlib import osutils  | 
21  | 
||
| 
1551.12.29
by Aaron Bentley
 Copy and extend patch date formatting code, add patch-date parsing  | 
22  | 
|
| 
1551.12.28
by Aaron Bentley
 Move bundle timestamp code to timestamp  | 
23  | 
def format_highres_date(t, offset=0):  | 
24  | 
"""Format a date, such that it includes higher precision in the  | 
|
25  | 
    seconds field.
 | 
|
26  | 
||
27  | 
    :param t:   The local time in fractional seconds since the epoch
 | 
|
28  | 
    :type t: float
 | 
|
29  | 
    :param offset:  The timezone offset in integer seconds
 | 
|
30  | 
    :type offset: int
 | 
|
31  | 
||
32  | 
    Example: format_highres_date(time.time(), -time.timezone)
 | 
|
33  | 
    this will return a date stamp for right now,
 | 
|
34  | 
    formatted for the local timezone.
 | 
|
35  | 
||
36  | 
    >>> from bzrlib.osutils import format_date
 | 
|
37  | 
    >>> format_date(1120153132.350850105, 0)
 | 
|
38  | 
    'Thu 2005-06-30 17:38:52 +0000'
 | 
|
39  | 
    >>> format_highres_date(1120153132.350850105, 0)
 | 
|
40  | 
    'Thu 2005-06-30 17:38:52.350850105 +0000'
 | 
|
41  | 
    >>> format_date(1120153132.350850105, -5*3600)
 | 
|
42  | 
    'Thu 2005-06-30 12:38:52 -0500'
 | 
|
43  | 
    >>> format_highres_date(1120153132.350850105, -5*3600)
 | 
|
44  | 
    'Thu 2005-06-30 12:38:52.350850105 -0500'
 | 
|
45  | 
    >>> format_highres_date(1120153132.350850105, 7200)
 | 
|
46  | 
    'Thu 2005-06-30 19:38:52.350850105 +0200'
 | 
|
47  | 
    >>> format_highres_date(1152428738.867522, 19800)
 | 
|
48  | 
    'Sun 2006-07-09 12:35:38.867522001 +0530'
 | 
|
49  | 
    """
 | 
|
50  | 
assert isinstance(t, float)  | 
|
51  | 
||
52  | 
    # This has to be formatted for "original" date, so that the
 | 
|
53  | 
    # revision XML entry will be reproduced faithfully.
 | 
|
54  | 
if offset is None:  | 
|
55  | 
offset = 0  | 
|
56  | 
tt = time.gmtime(t + offset)  | 
|
57  | 
||
58  | 
return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)  | 
|
59  | 
            # Get the high-res seconds, but ignore the 0
 | 
|
60  | 
+ ('%.9f' % (t - int(t)))[1:]  | 
|
61  | 
+ ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))  | 
|
62  | 
||
63  | 
||
64  | 
def unpack_highres_date(date):  | 
|
65  | 
"""This takes the high-resolution date stamp, and  | 
|
66  | 
    converts it back into the tuple (timestamp, timezone)
 | 
|
67  | 
    Where timestamp is in real UTC since epoch seconds, and timezone is an
 | 
|
68  | 
    integer number of seconds offset.
 | 
|
69  | 
||
70  | 
    :param date: A date formated by format_highres_date
 | 
|
71  | 
    :type date: string
 | 
|
72  | 
||
73  | 
    >>> import time, random
 | 
|
74  | 
    >>> unpack_highres_date('Thu 2005-06-30 12:38:52.350850105 -0500')
 | 
|
75  | 
    (1120153132.3508501, -18000)
 | 
|
76  | 
    >>> unpack_highres_date('Thu 2005-06-30 17:38:52.350850105 +0000')
 | 
|
77  | 
    (1120153132.3508501, 0)
 | 
|
78  | 
    >>> unpack_highres_date('Thu 2005-06-30 19:38:52.350850105 +0200')
 | 
|
79  | 
    (1120153132.3508501, 7200)
 | 
|
80  | 
    >>> unpack_highres_date('Sun 2006-07-09 12:35:38.867522001 +0530')
 | 
|
81  | 
    (1152428738.867522, 19800)
 | 
|
82  | 
    >>> from bzrlib.osutils import local_time_offset
 | 
|
83  | 
    >>> t = time.time()
 | 
|
84  | 
    >>> o = local_time_offset()
 | 
|
85  | 
    >>> t2, o2 = unpack_highres_date(format_highres_date(t, o))
 | 
|
86  | 
    >>> t == t2
 | 
|
87  | 
    True
 | 
|
88  | 
    >>> o == o2
 | 
|
89  | 
    True
 | 
|
90  | 
    >>> t -= 24*3600*365*2 # Start 2 years ago
 | 
|
91  | 
    >>> o = -12*3600
 | 
|
92  | 
    >>> for count in xrange(500):
 | 
|
93  | 
    ...   t += random.random()*24*3600*30
 | 
|
94  | 
    ...   o = ((o/3600 + 13) % 25 - 12)*3600 # Add 1 wrap around from [-12, 12]
 | 
|
95  | 
    ...   date = format_highres_date(t, o)
 | 
|
96  | 
    ...   t2, o2 = unpack_highres_date(date)
 | 
|
97  | 
    ...   if t != t2 or o != o2:
 | 
|
98  | 
    ...      print 'Failed on date %r, %s,%s diff:%s' % (date, t, o, t2-t)
 | 
|
99  | 
    ...      break
 | 
|
100  | 
||
101  | 
    """
 | 
|
102  | 
    # Up until the first period is a datestamp that is generated
 | 
|
103  | 
    # as normal from time.strftime, so use time.strptime to
 | 
|
104  | 
    # parse it
 | 
|
105  | 
dot_loc = date.find('.')  | 
|
106  | 
if dot_loc == -1:  | 
|
107  | 
raise ValueError(  | 
|
108  | 
'Date string does not contain high-precision seconds: %r' % date)  | 
|
109  | 
base_time = time.strptime(date[:dot_loc], "%a %Y-%m-%d %H:%M:%S")  | 
|
110  | 
fract_seconds, offset = date[dot_loc:].split()  | 
|
111  | 
fract_seconds = float(fract_seconds)  | 
|
112  | 
||
113  | 
offset = int(offset)  | 
|
114  | 
||
115  | 
hours = int(offset / 100)  | 
|
116  | 
minutes = (offset % 100)  | 
|
117  | 
seconds_offset = (hours * 3600) + (minutes * 60)  | 
|
118  | 
||
119  | 
    # time.mktime returns localtime, but calendar.timegm returns UTC time
 | 
|
120  | 
timestamp = calendar.timegm(base_time)  | 
|
121  | 
timestamp -= seconds_offset  | 
|
122  | 
    # Add back in the fractional seconds
 | 
|
123  | 
timestamp += fract_seconds  | 
|
124  | 
return (timestamp, seconds_offset)  | 
|
| 
1551.12.29
by Aaron Bentley
 Copy and extend patch date formatting code, add patch-date parsing  | 
125  | 
|
126  | 
||
127  | 
def format_patch_date(secs, offset=0):  | 
|
128  | 
"""Format a POSIX timestamp and optional offset as a patch-style date.  | 
|
129  | 
||
130  | 
    Inverse of parse_patch_date.
 | 
|
131  | 
    """
 | 
|
| 
2425.6.1
by Martin Pool
 Fix formatting of timezones in bundles and merge directives.  | 
132  | 
assert offset % 60 == 0, \  | 
133  | 
"can't represent timezone %s offset by fractional minutes" % offset  | 
|
134  | 
    # so that we don't need to do calculations on pre-epoch times, 
 | 
|
135  | 
    # which doesn't work with win32 python gmtime, we always
 | 
|
136  | 
    # give the epoch in utc
 | 
|
137  | 
if secs == 0:  | 
|
138  | 
offset = 0  | 
|
139  | 
if secs + offset < 0:  | 
|
140  | 
from warnings import warn  | 
|
141  | 
warn("gmtime of negative time (%s, %s) may not work on Windows" %  | 
|
142  | 
(secs, offset))  | 
|
| 
2425.6.2
by Martin Pool
 Make timestamps use existing format_date; document that function more  | 
143  | 
return osutils.format_date(secs, offset=offset,  | 
144  | 
date_fmt='%Y-%m-%d %H:%M:%S')  | 
|
| 
1551.12.29
by Aaron Bentley
 Copy and extend patch date formatting code, add patch-date parsing  | 
145  | 
|
146  | 
||
147  | 
def parse_patch_date(date_str):  | 
|
148  | 
"""Parse a patch-style date into a POSIX timestamp and offset.  | 
|
149  | 
||
150  | 
    Inverse of format_patch_date.
 | 
|
151  | 
    """
 | 
|
152  | 
secs_str = date_str[:-6]  | 
|
| 
2425.6.1
by Martin Pool
 Fix formatting of timezones in bundles and merge directives.  | 
153  | 
offset_str = date_str[-5:]  | 
154  | 
assert len(offset_str) == 5, \  | 
|
155  | 
"invalid timezone %r" % offset_str  | 
|
156  | 
offset_hours, offset_mins = offset_str[:3], offset_str[3:]  | 
|
157  | 
offset = int(offset_hours) * 3600 + int(offset_mins) * 60  | 
|
| 
1551.12.29
by Aaron Bentley
 Copy and extend patch date formatting code, add patch-date parsing  | 
158  | 
tm_time = time.strptime(secs_str, '%Y-%m-%d %H:%M:%S')  | 
159  | 
    # adjust seconds according to offset before converting to POSIX
 | 
|
160  | 
    # timestamp, to avoid edge problems
 | 
|
161  | 
tm_time = tm_time[:5] + (tm_time[5] - offset,) + tm_time[6:]  | 
|
162  | 
secs = calendar.timegm(tm_time)  | 
|
163  | 
return secs, offset  |