Commits

Dan Connolly  committed 2d651ea

date handling in OFX, python, JSON, JavaScript, and Angular
- milliseconds since the epoch seems to be best practice for dates in JSON

  • Participants
  • Parent commits 36197a1

Comments (0)

Files changed (4)

File finquick/models.py

 
 def _json_val(x):
     '''
+    Suitable for use with JavaScript Date(x)
+
+    .. todo:: make tests work in any timezone.
+
     >>> _json_val(datetime.datetime(2012, 5, 10, 12, 5, 6, 804699))
-    [2012, 5, 10, 12, 5, 6, 804699]
+    1336651506804
+    >>> _json_val(datetime.datetime(2010, 2, 12, 9, 50, 55))
+    1265968255000
+    >>> _json_val(datetime.datetime(2010, 2, 16))
+    1266278400000
     >>> _json_val(datetime.timedelta(0, 64, 130006))
     64130
     '''
+
     if x is None:
         return x
 
     if t in (type(''), type(u''), type(1), type(True)):
         return x
     elif t is datetime.date:
-        return [getattr(x, f) for f in ('year', 'month', 'day')]
+        return _json_val(x - _epochD)
     elif t is datetime.datetime:
-        return [getattr(x, f) for f in ('year', 'month', 'day',
-                                        'hour', 'minute', 'second',
-                                        'microsecond')]
+        return _json_val(x - (_epochZ if x.tzinfo else _epochLT))
     elif t is datetime.timedelta:
-        return x.microseconds / 1000 + (1000 * x.seconds)
+        return x.microseconds / 1000 + (1000 * (x.seconds +
+                                                (24 * 60 * 60) * x.days))
     elif t is Decimal:
         return str(x)
     else:
             for r in results]
 
 
+class FixedOffset(datetime.tzinfo):
+# ack: http://docs.python.org/library/datetime.html#tzinfo-objects
+    """Fixed offset in hours east from UTC."""
+
+    def __init__(self, offset, name):
+        self._hrs = offset
+        self.__offset = datetime.timedelta(minutes = offset * 60)
+        self.__name = name
+
+    def __repr__(self):
+        return '[%d:%s]' % (self._hrs, self.__name)
+
+    def utcoffset(self, dt):
+        return self.__offset
+
+    def tzname(self, dt):
+        return self.__name
+
+    def dst(self, dt):
+        return ZERO
+
+ZERO = datetime.timedelta(0)
+_epochZ = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, FixedOffset(0, 'UTC'))
+_epochLT = _epochZ.replace(tzinfo=None)
+_epochD = _epochLT.date()
+
+
 class Account(Base, GuidMixin):
     __tablename__ = 'accounts'
     name = Column(String)

File finquick/ofxin.py

 from sqlalchemy.types import String, Integer, DATETIME
 
 import models
+from models import FixedOffset
 
 log = logging.getLogger(__name__)
 
         >>> OFXParser.parse_date('20120423201548.648[-4:EDT]')
         datetime.datetime(2012, 4, 23, 20, 15, 48, 648000, tzinfo=[-4:EDT])
 
+        >>> models._json_val(OFXParser.parse_date('20120423201548.648[-4:EDT]'))
+        1335226548648
+
         >>> OFXParser.parse_date('20070315')
         datetime.date(2007, 3, 15)
         '''
 def _or(e1, e2):
     return e1 if e1 is not None else e2
 
-class FixedOffset(datetime.tzinfo):
-# ack: http://docs.python.org/library/datetime.html#tzinfo-objects
-    """Fixed offset in hours east from UTC."""
-
-    def __init__(self, offset, name):
-        self._hrs = offset
-        self.__offset = datetime.timedelta(minutes = offset * 60)
-        self.__name = name
-
-    def __repr__(self):
-        return '[%d:%s]' % (self._hrs, self.__name)
-
-    def utcoffset(self, dt):
-        return self.__offset
-
-    def tzname(self, dt):
-        return self.__name
-
-    def dst(self, dt):
-        return ZERO
-
-ZERO = datetime.timedelta(0)
-
 
 class dotelt(object):
     def __init__(self, e):

File finquick/static/accounts.html

 
     <table><caption>OFX Import</caption>
       <tr>
-	<th>Financial Institution</th><td>{{ofx_prep.summary.org}}</td>
+	<th>Financial Institution</th>
+	<th>Server Date</th>
       </tr>
       <tr>
-	<th>Server Date</th><td>{{ofx_prep.summary.dtserver}}</td>
+	<td>{{ofx_prep.summary.org}}</td>
+	<td>{{mkdate(ofx_prep.summary.dtserver) | date}}</td>
       </tr>
     </table>
     <table>
     </thead>
     <tbody>
       <tr ng-repeat="tx in ofx_prep.transactions">
-	<td>{{tx.dtposted}}</td>
+	<td>{{mkdate(tx.dtposted) | date}}</td>
 	<td>{{tx.name}}</td>
 	<td>{{tx.trnamt / 100 | currency }}</td>
       </tr>

File finquick/static/fin.js

 	alert(elt.value);
     }
 
+    $scope.mkdate = function(x) { return new Date(x) };
+
     $scope.prepare = function() {
 	console.log('in prepare() scope.ofx_file:' + $scope.ofx_file);
 	// http://www.w3.org/TR/FileAPI/