From 9a4f4d782ba39cf15012628012db3f6f20bf714e Mon Sep 17 00:00:00 2001 From: Wirawan Purwanto Date: Thu, 16 Oct 2014 15:56:16 -0400 Subject: [PATCH] * Added first implementation (and test harness) for idatetime datatype. --- TESTS/test_datetime.py | 54 +++++++++++++++++++++ datetime0_idt.py | 103 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 TESTS/test_datetime.py create mode 100644 datetime0_idt.py diff --git a/TESTS/test_datetime.py b/TESTS/test_datetime.py new file mode 100644 index 0000000..27d9dc2 --- /dev/null +++ b/TESTS/test_datetime.py @@ -0,0 +1,54 @@ +""" +Test routines for wpylib.datetime module (and related submodules). +""" + +from time import localtime, gmtime, strftime + +from wpylib.datetime0_idt import idatetime +from wpylib.datetime import utime_to_iso + + + +def test_idt_01(): + """[20141016] + Basic idatetime tests. + """ + iidt = 20141201083724315 + idt = idatetime(iidt) + print "integer value = %+18d" % idt.idt + print "iso8601 format = %s" % idt.str_iso8601() + + +def test_u2i_01(): + """[20141016] + Testing utime_to_iso subroutine. + + Output: + + unix time = 1413475094.058478 + time interpretation (local) = Thu Oct 16 11:58:14 EDT 2014 + utime_to_iso output (local) = 2014-10-16 11:58:14 -04:00 + utime_to_iso output (local/iso8601) = 2014-10-16T11:58:14.058478116-04:00 + time interpretation (utc) = Thu Oct 16 15:58:14 EST 2014 + utime_to_iso output (utc) = 2014-10-16 15:58:14 +00:00 + utime_to_iso output (utc/iso8601) = 2014-10-16T15:58:14.058478116Z + utime_to_iso output (utc/idtstamp) = 2014-10-16T15:58:14.058 + + """ + unix_time = 1413475094.058478 + str_time = utime_to_iso(unix_time, local=True) + str_gmtime = utime_to_iso(unix_time, local=False) + print "unix time = ", "%.16g" % unix_time + + print "time interpretation (local) = ", strftime("%a %b %e %H:%M:%S %Z %Y", localtime(unix_time)) + print "utime_to_iso output (local) = ", str_time + print "utime_to_iso output (local/iso8601) = ", utime_to_iso(unix_time, local=True, fmt='iso8601') + + print "time interpretation (utc) = ", strftime("%a %b %e %H:%M:%S %Z %Y", gmtime(unix_time)) + print "utime_to_iso output (utc) = ", str_gmtime + print "utime_to_iso output (utc/iso8601) = ", utime_to_iso(unix_time, local=False, fmt='iso8601') + print "utime_to_iso output (utc/idtstamp) = ", utime_to_iso(unix_time, local=False, fmt='idtstamp') + + + + diff --git a/datetime0_idt.py b/datetime0_idt.py new file mode 100644 index 0000000..73c417d --- /dev/null +++ b/datetime0_idt.py @@ -0,0 +1,103 @@ +# +# wpylib.datetime0_idt +# Created: 20141015 +# Wirawan Purwanto +# +# Simple date/time stamp using 64-bit integer. +# This module is an internal module; the exported name will +# be put in wpylib.datetime module. +# + +""" +wplib.datetime0_idt module + +Simple date/time stamp using 64-bit integer. +The primary motivation of creating this class is to store date/time +information in the most compact way, while keeping the ease of +human readability. + +The internal format is very simple: + +YYYYMMDDhhmmssfff + +where: + - YYYY = year (0 < YYYY <= 9999) + - MM = month (1 <= MM <= 12) + - DD = day + - hh = hour (0 <= hh < 24) + - mm = minutes + - ss = seconds + - fff = milliseconds + +The time is always expressed in terms of UTC to eliminate ambiguity of +time zone, daylight savings time, etc. +CAVEAT: The resolution of the time is only on the order of millisecond. + +This is a 17-decimal-digit integer, which fits in a 64-bit range (9.22e+18). + +""" + +from wpylib.params import struct + + +class idatetime(object): + """Simple 8-byte integer representation of a date/time stamp. + """ + def __init__(self, idt=None): + if idt != None: + self.idt = idt + + def validate(self): + raise NotImplementedError + + def split_values(self): + """Splits the compact datetime into components. + Warning: the values are NOT validated. + """ + idt = self.idt + s = str(idt) + R = struct() + #R.YYYY, R.MM, R.DD, R.hh, R.mm, R.ss, R.fff # names are too cryptic + # Use same member names as in datetime (in sofar it is possible): + R.year, R.month, R.day, R.hour, R.minute, R.second, R.millisecond = map(int, [ + s[:-13], # year + s[-13:-11], # month + s[-11:-9], # day + s[-9:-7], # hour + s[-7:-5], # min + s[-5:-3], # sec + s[-3:] # millisec + ]) + R.microsecond = R.millisecond * 1000 + return R + + def to_datetime(self): + """Converts the object value to standard python datetime object. + """ + from datetime import datetime + R = self.split_values() + dt = datetime(R.year, R.month, R.day, R.hour, R.minute, R.second, R.microsecond) + ''' + idt = self.idt + s = str(idt) + YYYY, MM, DD, hh, mm, ss, ms = map(int, [ + s[:-13], # year + s[-13:-11], # month + s[-11:-9], # day + s[-9:-7], # hour + s[-7:-5], # min + s[-5:-3], # sec + s[-3:] # millisec + ]) + dt = datetime(YYYY, MM, DD, hh, mm, ss, fff*1000) + ''' + return dt + + def str_iso8601(self): + """Outputs the object according to ISO-8601 combined date/time format. + No time zone is shown.""" + R = self.split_values() + fmt = "%(year)04d-%(month)02d-%(day)02dT%(hour)02d:%(minute)02d:%(second)02d.%(millisecond)03d" + return fmt % R + +