aboutsummaryrefslogtreecommitdiff
path: root/scripts/rpki/sundial.py
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2007-11-14 01:24:04 +0000
committerRob Austein <sra@hactrn.net>2007-11-14 01:24:04 +0000
commitb617eaa787b2022da92e7b3b1e3dede866b5f32b (patch)
treea035fb3432db080fc36fd0f0991ca9a1f4247a06 /scripts/rpki/sundial.py
parent7dce888f15e42d4214ee9a6c2ede08098f62bbae (diff)
Hide most of the time arithmetic in an abstraction based on
datetime.datetime. svn path=/scripts/biz-certs/Bob-CA.srl; revision=1285
Diffstat (limited to 'scripts/rpki/sundial.py')
-rw-r--r--scripts/rpki/sundial.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/scripts/rpki/sundial.py b/scripts/rpki/sundial.py
new file mode 100644
index 00000000..2360732d
--- /dev/null
+++ b/scripts/rpki/sundial.py
@@ -0,0 +1,110 @@
+# $Id$
+
+"""Unified RPKI date/time handling, based on the standard Python datetime module.
+
+Module name chosen to sidestep a nightmare of import-related errors
+that occur with the more obvious module names.
+"""
+
+import datetime as pydatetime
+
+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 fromUTCTime(cls, x):
+ """Convert from ASN.1 UTCTime."""
+ return cls.strptime(x, "%y%m%d%H%M%SZ")
+
+ def toUTCTime(self):
+ """Convert to ASN.1 UTCTime."""
+ return self.strftime("%y%m%d%H%M%SZ")
+
+ @classmethod
+ def fromGeneralizedTime(cls, x):
+ """Convert from ASN.1 GeneralizedTime."""
+ return cls.strptime(x, "%Y%m%d%H%M%SZ")
+
+ def toGeneralizedTime(self):
+ """Convert to ASN.1 GeneralizedTime."""
+ return self.strftime("%Y%m%d%H%M%SZ")
+
+ @classmethod
+ def fromASN1tuple(cls, x):
+ """Convert from ASN.1 tuple representation."""
+ assert isinstance(x, tuple) and len(x) == 2 and x[0] in ("utcTime", "generalTime")
+ if x[0] == "utcTime":
+ return cls.fromUTCTime(x)
+ else:
+ return cls.fromGeneralizedTime(x)
+
+ ## @var PKIX_threshhold
+ # Threshold specified in RFC 3280 for switchover from UTCTime to GeneralizedTime.
+
+ PKIX_threshhold = pydatetime.datetime(2050, 1, 1)
+
+ def toASN1tuple(self):
+ """Convert to ASN.1 tuple representation."""
+ if self < self.PKIX_threshhold:
+ return "utcTime", self.toUTCTime()
+ else:
+ return "generalTime", self.toGeneralizedTime()
+
+ @classmethod
+ def fromXMLtime(cls, x):
+ """Convert from XML time representation."""
+ 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")
+
+ @classmethod
+ def _cast(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 __add__(self, other):
+ """Force correct class for timedelta results."""
+ return self._cast(pydatetime.datetime.__add__(self, other))
+
+ def __sub__(self, other):
+ """Force correct class for timedelta results."""
+ return self._cast(pydatetime.datetime.__sub__(self, other))
+
+# Alias to simplify imports for callers
+
+timedelta = pydatetime.timedelta
+
+if __name__ == "__main__":
+
+ now = datetime.utcnow()
+ print now
+ print repr(now)
+ print now.strftime("%s")
+ print now.toUTCTime()
+ print now.toGeneralizedTime()
+ print now.toASN1tuple()
+ print now.toXMLtime()
+
+ print
+
+ then = now
+ then += timedelta(days = 30)
+ print then
+ print repr(then)
+ print then.strftime("%s")
+ print then.toUTCTime()
+ print then.toGeneralizedTime()
+ print then.toASN1tuple()
+ print then.toXMLtime()