aboutsummaryrefslogtreecommitdiff
path: root/rpki/sundial.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpki/sundial.py')
-rw-r--r--rpki/sundial.py456
1 files changed, 228 insertions, 228 deletions
diff --git a/rpki/sundial.py b/rpki/sundial.py
index 60037277..0381599f 100644
--- a/rpki/sundial.py
+++ b/rpki/sundial.py
@@ -48,257 +48,257 @@ import datetime as pydatetime
import re
def now():
- """
- Get current timestamp.
- """
-
- return datetime.utcnow()
-
-class ParseFailure(Exception):
- """
- Parse failure constructing timedelta.
- """
-
-class datetime(pydatetime.datetime):
- """
- RPKI extensions to standard datetime.datetime class. All work here
- is in UTC, so we use naive datetime objects.
- """
-
- def totimestamp(self):
- """
- Convert to seconds from epoch (like time.time()). Conversion
- method is a bit silly, but avoids time module timezone whackiness.
- """
-
- return int(self.strftime("%s"))
-
- @classmethod
- def fromXMLtime(cls, x):
- """
- Convert from XML time representation.
- """
-
- if x is None:
- return None
- else:
- return cls.strptime(x, "%Y-%m-%dT%H:%M:%SZ")
-
- def toXMLtime(self):
"""
- Convert to XML time representation.
+ Get current timestamp.
"""
- return self.strftime("%Y-%m-%dT%H:%M:%SZ")
-
- def __str__(self):
- return self.toXMLtime()
-
- @classmethod
- def from_datetime(cls, x):
- """
- Convert a datetime.datetime object into this subclass. This is
- whacky due to the weird constructors for datetime.
- """
-
- return cls.combine(x.date(), x.time())
-
- def to_datetime(self):
- """
- Convert to a datetime.datetime object. In most cases this
- shouldn't be necessary, but convincing SQL interfaces to use
- subclasses of datetime can be hard.
- """
-
- return pydatetime.datetime(year = self.year, month = self.month, day = self.day,
- hour = self.hour, minute = self.minute, second = self.second,
- microsecond = 0, tzinfo = None)
-
-
- @classmethod
- def fromOpenSSL(cls, x):
- """
- Convert from the format OpenSSL's command line tool uses into this
- subclass. May require rewriting if we run into locale problems.
- """
+ return datetime.utcnow()
- if x.startswith("notBefore=") or x.startswith("notAfter="):
- x = x.partition("=")[2]
- return cls.strptime(x, "%b %d %H:%M:%S %Y GMT")
-
- @classmethod
- def from_sql(cls, x):
- """
- Convert from SQL storage format.
- """
-
- return cls.from_datetime(x)
-
- def to_sql(self):
- """
- Convert to SQL storage format.
- """
-
- return self.to_datetime()
-
- def later(self, other):
+class ParseFailure(Exception):
"""
- Return the later of two timestamps.
+ Parse failure constructing timedelta.
"""
- return other if other > self else self
-
- def earlier(self, other):
+class datetime(pydatetime.datetime):
"""
- Return the earlier of two timestamps.
+ RPKI extensions to standard datetime.datetime class. All work here
+ is in UTC, so we use naive datetime objects.
"""
- return other if other < self else self
-
- def __add__(self, y): return _cast(pydatetime.datetime.__add__(self, y))
- def __radd__(self, y): return _cast(pydatetime.datetime.__radd__(self, y))
- def __rsub__(self, y): return _cast(pydatetime.datetime.__rsub__(self, y))
- def __sub__(self, y): return _cast(pydatetime.datetime.__sub__(self, y))
+ def totimestamp(self):
+ """
+ Convert to seconds from epoch (like time.time()). Conversion
+ method is a bit silly, but avoids time module timezone whackiness.
+ """
+
+ return int(self.strftime("%s"))
+
+ @classmethod
+ def fromXMLtime(cls, x):
+ """
+ Convert from XML time representation.
+ """
+
+ if x is None:
+ return None
+ else:
+ return cls.strptime(x, "%Y-%m-%dT%H:%M:%SZ")
+
+ def toXMLtime(self):
+ """
+ Convert to XML time representation.
+ """
+
+ return self.strftime("%Y-%m-%dT%H:%M:%SZ")
+
+ def __str__(self):
+ return self.toXMLtime()
+
+ @classmethod
+ def from_datetime(cls, x):
+ """
+ Convert a datetime.datetime object into this subclass. This is
+ whacky due to the weird constructors for datetime.
+ """
+
+ return cls.combine(x.date(), x.time())
+
+ def to_datetime(self):
+ """
+ Convert to a datetime.datetime object. In most cases this
+ shouldn't be necessary, but convincing SQL interfaces to use
+ subclasses of datetime can be hard.
+ """
+
+ return pydatetime.datetime(year = self.year, month = self.month, day = self.day,
+ hour = self.hour, minute = self.minute, second = self.second,
+ microsecond = 0, tzinfo = None)
+
+
+ @classmethod
+ def fromOpenSSL(cls, x):
+ """
+ Convert from the format OpenSSL's command line tool uses into this
+ subclass. May require rewriting if we run into locale problems.
+ """
+
+ if x.startswith("notBefore=") or x.startswith("notAfter="):
+ x = x.partition("=")[2]
+ return cls.strptime(x, "%b %d %H:%M:%S %Y GMT")
+
+ @classmethod
+ def from_sql(cls, x):
+ """
+ Convert from SQL storage format.
+ """
+
+ return cls.from_datetime(x)
+
+ def to_sql(self):
+ """
+ Convert to SQL storage format.
+ """
+
+ return self.to_datetime()
+
+ def later(self, other):
+ """
+ Return the later of two timestamps.
+ """
+
+ return other if other > self else self
+
+ def earlier(self, other):
+ """
+ Return the earlier of two timestamps.
+ """
+
+ return other if other < self else self
+
+ def __add__(self, y): return _cast(pydatetime.datetime.__add__(self, y))
+ def __radd__(self, y): return _cast(pydatetime.datetime.__radd__(self, y))
+ def __rsub__(self, y): return _cast(pydatetime.datetime.__rsub__(self, y))
+ def __sub__(self, y): return _cast(pydatetime.datetime.__sub__(self, y))
+
+ @classmethod
+ def DateTime_or_None(cls, s):
+ """
+ MySQLdb converter. Parse as this class if we can, let the default
+ MySQLdb DateTime_or_None() converter deal with failure cases.
+ """
+
+ for sep in " T":
+ d, _, t = s.partition(sep) # pylint: disable=W0612
+ if t:
+ try:
+ return cls(*[int(x) for x in d.split("-") + t.split(":")])
+ except: # pylint: disable=W0702
+ break
+
+ from rpki.mysql_import import MySQLdb
+ return MySQLdb.times.DateTime_or_None(s)
- @classmethod
- def DateTime_or_None(cls, s):
- """
- MySQLdb converter. Parse as this class if we can, let the default
- MySQLdb DateTime_or_None() converter deal with failure cases.
+class timedelta(pydatetime.timedelta):
"""
+ Timedelta with text parsing. This accepts two input formats:
- for sep in " T":
- d, _, t = s.partition(sep) # pylint: disable=W0612
- if t:
- try:
- return cls(*[int(x) for x in d.split("-") + t.split(":")])
- except: # pylint: disable=W0702
- break
+ - A simple integer, indicating a number of seconds.
- from rpki.mysql_import import MySQLdb
- return MySQLdb.times.DateTime_or_None(s)
+ - A string of the form "uY vW wD xH yM zS" where u, v, w, x, y, and z
+ are integers and Y, W, D, H, M, and S indicate years, weeks, days,
+ hours, minutes, and seconds. All of the fields are optional, but
+ at least one must be specified. Eg,"3D4H" means "three days plus
+ four hours".
-class timedelta(pydatetime.timedelta):
- """
- Timedelta with text parsing. This accepts two input formats:
-
- - A simple integer, indicating a number of seconds.
-
- - A string of the form "uY vW wD xH yM zS" where u, v, w, x, y, and z
- are integers and Y, W, D, H, M, and S indicate years, weeks, days,
- hours, minutes, and seconds. All of the fields are optional, but
- at least one must be specified. Eg,"3D4H" means "three days plus
- four hours".
-
- There is no "months" format, because the definition of a month is too
- fuzzy to be useful (what day is six months from August 30th?)
-
- Similarly, the "years" conversion may produce surprising results, as
- "one year" in conventional English does not refer to a fixed interval
- but rather a fixed (and in some cases undefined) offset within the
- Gregorian calendar (what day is one year from February 29th?) 1Y as
- implemented by this code refers to a specific number of seconds.
- If you mean 365 days or 52 weeks, say that instead.
- """
-
- ## @var regexp
- # Hideously ugly regular expression to parse the complex text form.
- # Tags are intended for use with re.MatchObject.groupdict() and map
- # directly to the keywords expected by the timedelta constructor.
-
- regexp = re.compile("\\s*".join(("^",
- "(?:(?P<years>\\d+)Y)?",
- "(?:(?P<weeks>\\d+)W)?",
- "(?:(?P<days>\\d+)D)?",
- "(?:(?P<hours>\\d+)H)?",
- "(?:(?P<minutes>\\d+)M)?",
- "(?:(?P<seconds>\\d+)S)?",
- "$")),
- re.I)
-
- ## @var years_to_seconds
- # Conversion factor from years to seconds (value furnished by the
- # "units" program).
-
- years_to_seconds = 31556926
-
- @classmethod
- def parse(cls, arg):
- """
- Parse text into a timedelta object.
- """
+ There is no "months" format, because the definition of a month is too
+ fuzzy to be useful (what day is six months from August 30th?)
- if not isinstance(arg, str):
- return cls(seconds = arg)
- elif arg.isdigit():
- return cls(seconds = int(arg))
- else:
- match = cls.regexp.match(arg)
- if match:
- #return cls(**dict((k, int(v)) for (k, v) in match.groupdict().items() if v is not None))
- d = match.groupdict("0")
- for k, v in d.iteritems():
- d[k] = int(v)
- d["days"] += d.pop("weeks") * 7
- d["seconds"] += d.pop("years") * cls.years_to_seconds
- return cls(**d)
- else:
- raise ParseFailure("Couldn't parse timedelta %r" % (arg,))
-
- def convert_to_seconds(self):
- """
- Convert a timedelta interval to seconds.
+ Similarly, the "years" conversion may produce surprising results, as
+ "one year" in conventional English does not refer to a fixed interval
+ but rather a fixed (and in some cases undefined) offset within the
+ Gregorian calendar (what day is one year from February 29th?) 1Y as
+ implemented by this code refers to a specific number of seconds.
+ If you mean 365 days or 52 weeks, say that instead.
"""
- return self.days * 24 * 60 * 60 + self.seconds
+ ## @var regexp
+ # Hideously ugly regular expression to parse the complex text form.
+ # Tags are intended for use with re.MatchObject.groupdict() and map
+ # directly to the keywords expected by the timedelta constructor.
+
+ regexp = re.compile("\\s*".join(("^",
+ "(?:(?P<years>\\d+)Y)?",
+ "(?:(?P<weeks>\\d+)W)?",
+ "(?:(?P<days>\\d+)D)?",
+ "(?:(?P<hours>\\d+)H)?",
+ "(?:(?P<minutes>\\d+)M)?",
+ "(?:(?P<seconds>\\d+)S)?",
+ "$")),
+ re.I)
+
+ ## @var years_to_seconds
+ # Conversion factor from years to seconds (value furnished by the
+ # "units" program).
+
+ years_to_seconds = 31556926
+
+ @classmethod
+ def parse(cls, arg):
+ """
+ Parse text into a timedelta object.
+ """
+
+ if not isinstance(arg, str):
+ return cls(seconds = arg)
+ elif arg.isdigit():
+ return cls(seconds = int(arg))
+ else:
+ match = cls.regexp.match(arg)
+ if match:
+ #return cls(**dict((k, int(v)) for (k, v) in match.groupdict().items() if v is not None))
+ d = match.groupdict("0")
+ for k, v in d.iteritems():
+ d[k] = int(v)
+ d["days"] += d.pop("weeks") * 7
+ d["seconds"] += d.pop("years") * cls.years_to_seconds
+ return cls(**d)
+ else:
+ raise ParseFailure("Couldn't parse timedelta %r" % (arg,))
+
+ def convert_to_seconds(self):
+ """
+ Convert a timedelta interval to seconds.
+ """
+
+ return self.days * 24 * 60 * 60 + self.seconds
+
+ @classmethod
+ def fromtimedelta(cls, x):
+ """
+ Convert a datetime.timedelta object into this subclass.
+ """
+
+ return cls(days = x.days, seconds = x.seconds, microseconds = x.microseconds)
+
+ def __abs__(self): return _cast(pydatetime.timedelta.__abs__(self))
+ def __add__(self, x): return _cast(pydatetime.timedelta.__add__(self, x))
+ def __div__(self, x): return _cast(pydatetime.timedelta.__div__(self, x))
+ def __floordiv__(self, x): return _cast(pydatetime.timedelta.__floordiv__(self, x))
+ def __mul__(self, x): return _cast(pydatetime.timedelta.__mul__(self, x))
+ def __neg__(self): return _cast(pydatetime.timedelta.__neg__(self))
+ def __pos__(self): return _cast(pydatetime.timedelta.__pos__(self))
+ def __radd__(self, x): return _cast(pydatetime.timedelta.__radd__(self, x))
+ def __rdiv__(self, x): return _cast(pydatetime.timedelta.__rdiv__(self, x))
+ def __rfloordiv__(self, x): return _cast(pydatetime.timedelta.__rfloordiv__(self, x))
+ def __rmul__(self, x): return _cast(pydatetime.timedelta.__rmul__(self, x))
+ def __rsub__(self, x): return _cast(pydatetime.timedelta.__rsub__(self, x))
+ def __sub__(self, x): return _cast(pydatetime.timedelta.__sub__(self, x))
- @classmethod
- def fromtimedelta(cls, x):
+def _cast(x):
"""
- Convert a datetime.timedelta object into this subclass.
+ Cast result of arithmetic operations back into correct subtype.
"""
- return cls(days = x.days, seconds = x.seconds, microseconds = x.microseconds)
-
- def __abs__(self): return _cast(pydatetime.timedelta.__abs__(self))
- def __add__(self, x): return _cast(pydatetime.timedelta.__add__(self, x))
- def __div__(self, x): return _cast(pydatetime.timedelta.__div__(self, x))
- def __floordiv__(self, x): return _cast(pydatetime.timedelta.__floordiv__(self, x))
- def __mul__(self, x): return _cast(pydatetime.timedelta.__mul__(self, x))
- def __neg__(self): return _cast(pydatetime.timedelta.__neg__(self))
- def __pos__(self): return _cast(pydatetime.timedelta.__pos__(self))
- def __radd__(self, x): return _cast(pydatetime.timedelta.__radd__(self, x))
- def __rdiv__(self, x): return _cast(pydatetime.timedelta.__rdiv__(self, x))
- def __rfloordiv__(self, x): return _cast(pydatetime.timedelta.__rfloordiv__(self, x))
- def __rmul__(self, x): return _cast(pydatetime.timedelta.__rmul__(self, x))
- def __rsub__(self, x): return _cast(pydatetime.timedelta.__rsub__(self, x))
- def __sub__(self, x): return _cast(pydatetime.timedelta.__sub__(self, x))
-
-def _cast(x):
- """
- Cast result of arithmetic operations back into correct subtype.
- """
-
- if isinstance(x, pydatetime.datetime):
- return datetime.from_datetime(x)
- if isinstance(x, pydatetime.timedelta):
- return timedelta.fromtimedelta(x)
- return x
+ if isinstance(x, pydatetime.datetime):
+ return datetime.from_datetime(x)
+ if isinstance(x, pydatetime.timedelta):
+ return timedelta.fromtimedelta(x)
+ return x
if __name__ == "__main__":
- def test(t):
- print
- print "str: ", t
- print "repr: ", repr(t)
- print "seconds since epoch:", t.strftime("%s")
- print "XMLtime: ", t.toXMLtime()
- print
+ def test(t):
+ print
+ print "str: ", t
+ print "repr: ", repr(t)
+ print "seconds since epoch:", t.strftime("%s")
+ print "XMLtime: ", t.toXMLtime()
+ print
- print
- print "Testing time conversion routines"
- test(now())
- test(now() + timedelta(days = 30))
- test(now() + timedelta.parse("3d5s"))
- test(now() + timedelta.parse(" 3d 5s "))
- test(now() + timedelta.parse("1y3d5h"))
+ print
+ print "Testing time conversion routines"
+ test(now())
+ test(now() + timedelta(days = 30))
+ test(now() + timedelta.parse("3d5s"))
+ test(now() + timedelta.parse(" 3d 5s "))
+ test(now() + timedelta.parse("1y3d5h"))