From: Zooko O'Whielacronx Date: Fri, 3 Apr 2009 22:59:04 +0000 (-0700) Subject: leases, time_format: modify time stamping in lease description X-Git-Tag: allmydata-tahoe-1.4.0~29 X-Git-Url: https://git.rkrishnan.org/pf/content/en/service/nxhtml.html?a=commitdiff_plain;h=b12a7f9ee84ad6d1ebee7dcdd3af2724e91d8525;p=tahoe-lafs%2Ftahoe-lafs.git leases, time_format: modify time stamping in lease description * emit lease expiry date in ISO-8601'ish format as well as Brian's format * rename iso_utc_time_to_localseconds() to iso_utc_time_to_seconds() * add iso_utc_date() * simplify the body of iso_utc_time_to_seconds() --- diff --git a/src/allmydata/scripts/tahoe_backup.py b/src/allmydata/scripts/tahoe_backup.py index b6e26441..e2b9bced 100644 --- a/src/allmydata/scripts/tahoe_backup.py +++ b/src/allmydata/scripts/tahoe_backup.py @@ -28,7 +28,7 @@ def parse_old_timestamp(s, options): # misleading. This returns seconds-since-epoch for an # ISO-8601-ish-formatted UTC time string. This might raise # ValueError if the string is not in the right format. - when = time_format.iso_utc_time_to_localseconds(s[:-1]) + when = time_format.iso_utc_time_to_seconds(s[:-1]) return when except ValueError: pass diff --git a/src/allmydata/test/test_storage.py b/src/allmydata/test/test_storage.py index aa0bd29e..d062426b 100644 --- a/src/allmydata/test/test_storage.py +++ b/src/allmydata/test/test_storage.py @@ -2026,9 +2026,9 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin): s = remove_tags(html) self.failUnlessIn("Expiration Enabled:" " expired leases will be removed", s) - date = time.strftime("%d-%b-%Y", time.gmtime(then)) - self.failUnlessIn("Leases created or last renewed before %s" - " will be considered expired." % date, s) + date = time.strftime("%Y-%m-%d (%d-%b-%Y) UTC", time.gmtime(then)) + substr = "Leases created or last renewed before %s will be considered expired." % date + self.failUnlessIn(substr, s) self.failUnlessIn(" recovered: 2 shares, 2 buckets (1 mutable / 1 immutable), ", s) d.addCallback(_check_html) return d diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py index 19ae70f5..5b747b96 100644 --- a/src/allmydata/test/test_util.py +++ b/src/allmydata/test/test_util.py @@ -763,28 +763,36 @@ class Limiter(unittest.TestCase): class TimeFormat(unittest.TestCase): def test_epoch(self): - s = time_format.iso_utc_time_to_localseconds("1970-01-01T00:00:01") + s = time_format.iso_utc_time_to_seconds("1970-01-01T00:00:01") self.failUnlessEqual(s, 1.0) - s = time_format.iso_utc_time_to_localseconds("1970-01-01_00:00:01") + s = time_format.iso_utc_time_to_seconds("1970-01-01_00:00:01") self.failUnlessEqual(s, 1.0) - s = time_format.iso_utc_time_to_localseconds("1970-01-01 00:00:01") + s = time_format.iso_utc_time_to_seconds("1970-01-01 00:00:01") self.failUnlessEqual(s, 1.0) self.failUnlessEqual(time_format.iso_utc(1.0), "1970-01-01_00:00:01") self.failUnlessEqual(time_format.iso_utc(1.0, sep=" "), "1970-01-01 00:00:01") now = time.time() + isostr = time_format.iso_utc(now) + timestamp = time_format.iso_utc_time_to_seconds(isostr) + self.failUnlessEqual(int(timestamp), int(now)) + def my_time(): return 1.0 self.failUnlessEqual(time_format.iso_utc(t=my_time), "1970-01-01_00:00:01") e = self.failUnlessRaises(ValueError, - time_format.iso_utc_time_to_localseconds, + time_format.iso_utc_time_to_seconds, "invalid timestring") self.failUnless("not a complete ISO8601 timestamp" in str(e)) - s = time_format.iso_utc_time_to_localseconds("1970-01-01_00:00:01.500") + s = time_format.iso_utc_time_to_seconds("1970-01-01_00:00:01.500") self.failUnlessEqual(s, 1.5) + # Look for daylight-savings-related errors. + thatmomentinmarch = time_format.iso_utc_time_to_seconds("2009-03-20 21:49:02.226536") + self.failUnlessEqual(thatmomentinmarch, 1237585742.226536) + class CacheDir(unittest.TestCase): def test_basic(self): basedir = "test_util/CacheDir/test_basic" diff --git a/src/allmydata/util/time_format.py b/src/allmydata/util/time_format.py index bb935896..926d7179 100644 --- a/src/allmydata/util/time_format.py +++ b/src/allmydata/util/time_format.py @@ -9,12 +9,17 @@ import datetime, re, time +def iso_utc_date(now=None, t=time.time): + if now is None: + now = t() + return datetime.datetime.utcfromtimestamp(now).isoformat()[:10] + def iso_utc(now=None, sep='_', t=time.time): if now is None: now = t() return datetime.datetime.utcfromtimestamp(now).isoformat(sep) -def iso_utc_time_to_localseconds(isotime, _conversion_re=re.compile(r"(?P\d{4})-(?P\d{2})-(?P\d{2})[T_ ](?P\d{2}):(?P\d{2}):(?P\d{2})(?P\.\d+)?")): +def iso_utc_time_to_seconds(isotime, _conversion_re=re.compile(r"(?P\d{4})-(?P\d{2})-(?P\d{2})[T_ ](?P\d{2}):(?P\d{2}):(?P\d{2})(?P\.\d+)?")): """ The inverse of iso_utc(). @@ -26,13 +31,16 @@ def iso_utc_time_to_localseconds(isotime, _conversion_re=re.compile(r"(?P\ raise ValueError, (isotime, "not a complete ISO8601 timestamp") year, month, day = int(m.group('year')), int(m.group('month')), int(m.group('day')) hour, minute, second = int(m.group('hour')), int(m.group('minute')), int(m.group('second')) - utcseconds = time.mktime( (year, month, day, hour, minute, second, 0, 1, 0) ) - localseconds = utcseconds - time.timezone subsecstr = m.group('subsecond') if subsecstr: subsecfloat = float(subsecstr) - localseconds += subsecfloat - return localseconds + else: + subsecfloat = 0 + + localsecondsnodst = time.mktime( (year, month, day, hour, minute, second, 0, 1, 0) ) + localsecondsnodst += subsecfloat + utcseconds = localsecondsnodst - time.timezone + return utcseconds def parse_duration(s): orig = s @@ -62,5 +70,5 @@ def parse_duration(s): def parse_date(s): # return seconds-since-epoch for the UTC midnight that starts the given # day - return int(iso_utc_time_to_localseconds(s + "T00:00:00")) + return int(iso_utc_time_to_seconds(s + "T00:00:00")) diff --git a/src/allmydata/web/storage.py b/src/allmydata/web/storage.py index d14e4295..29f2c3a9 100644 --- a/src/allmydata/web/storage.py +++ b/src/allmydata/web/storage.py @@ -3,6 +3,7 @@ import time, simplejson from nevow import rend, tags as T, inevow from allmydata.web.common import getxmlfile, abbreviate_time, get_arg from allmydata.util.abbreviate import abbreviate_space +from allmydata.util import time_format def remove_prefix(s, prefix): if not s.startswith(prefix): @@ -140,9 +141,10 @@ class StorageStatus(rend.Page): % abbreviate_time(lc.override_lease_duration)] else: assert lc.mode == "cutoff-date" - date = time.strftime("%d-%b-%Y", time.gmtime(lc.cutoff_date)) - ctx.tag["Leases created or last renewed before %s " - "will be considered expired." % date] + localizedutcdate = time.strftime("%d-%b-%Y", time.gmtime(lc.cutoff_date)) + isoutcdate = time_format.iso_utc_date(lc.cutoff_date) + ctx.tag["Leases created or last renewed before %s (%s) UTC " + "will be considered expired." % (isoutcdate, localizedutcdate, )] if len(lc.mode) > 2: ctx.tag[" The following sharetypes will be expired: ", " ".join(sorted(lc.sharetypes_to_expire)), "."]