##// END OF EJS Templates
Merge pull request #3525 from minrk/utc...
Matthias Bussonnier -
r11187:b5297e0b merge
parent child Browse files
Show More
@@ -0,0 +1,46 b''
1 # encoding: utf-8
2 """
3 Timezone utilities
4
5 Just UTC-awareness right now
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2013 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 from datetime import tzinfo, timedelta, datetime
20
21 #-----------------------------------------------------------------------------
22 # Code
23 #-----------------------------------------------------------------------------
24 # constant for zero offset
25 ZERO = timedelta(0)
26
27 class tzUTC(tzinfo):
28 """tzinfo object for UTC (zero offset)"""
29
30 def utcoffset(self, d):
31 return ZERO
32
33 def dst(self, d):
34 return ZERO
35
36 UTC = tzUTC()
37
38 def utc_aware(unaware):
39 """decorator for adding UTC tzinfo to datetime's utcfoo methods"""
40 def utc_method(*args, **kwargs):
41 dt = unaware(*args, **kwargs)
42 return dt.replace(tzinfo=UTC)
43 return utc_method
44
45 utcfromtimestamp = utc_aware(datetime.utcfromtimestamp)
46 utcnow = utc_aware(datetime.utcnow)
@@ -26,7 +26,7 b' from tornado import web'
26 26 from .nbmanager import NotebookManager
27 27 from IPython.nbformat import current
28 28 from IPython.utils.traitlets import Unicode, Instance
29
29 from IPython.utils import tz
30 30
31 31 #-----------------------------------------------------------------------------
32 32 # Classes
@@ -98,7 +98,7 b' class AzureNotebookManager(NotebookManager):'
98 98 raise web.HTTPError(500, u'Unreadable JSON notebook.')
99 99 # Todo: The last modified should actually be saved in the notebook document.
100 100 # We are just using the current datetime until that is implemented.
101 last_modified = datetime.datetime.utcnow()
101 last_modified = tz.utcnow()
102 102 return last_modified, nb
103 103
104 104 def write_notebook_object(self, nb, notebook_id=None):
@@ -28,6 +28,7 b' from tornado import web'
28 28 from .nbmanager import NotebookManager
29 29 from IPython.nbformat import current
30 30 from IPython.utils.traitlets import Unicode, Dict, Bool, TraitError
31 from IPython.utils import tz
31 32
32 33 #-----------------------------------------------------------------------------
33 34 # Classes
@@ -139,7 +140,7 b' class FileNotebookManager(NotebookManager):'
139 140 def read_notebook_object_from_path(self, path):
140 141 """read a notebook object from a path"""
141 142 info = os.stat(path)
142 last_modified = datetime.datetime.utcfromtimestamp(info.st_mtime)
143 last_modified = tz.utcfromtimestamp(info.st_mtime)
143 144 with open(path,'r') as f:
144 145 s = f.read()
145 146 try:
@@ -281,7 +282,7 b' class FileNotebookManager(NotebookManager):'
281 282 """construct the info dict for a given checkpoint"""
282 283 path = self.get_checkpoint_path(notebook_id, checkpoint_id)
283 284 stats = os.stat(path)
284 last_modified = datetime.datetime.utcfromtimestamp(stats.st_mtime)
285 last_modified = tz.utcfromtimestamp(stats.st_mtime)
285 286 info = dict(
286 287 checkpoint_id = checkpoint_id,
287 288 last_modified = last_modified,
@@ -33,7 +33,7 b" next_attr_name = '__next__' if py3compat.PY3 else 'next'"
33 33
34 34 # timestamp formats
35 35 ISO8601="%Y-%m-%dT%H:%M:%S.%f"
36 ISO8601_PAT=re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+$")
36 ISO8601_PAT=re.compile(r"^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+)Z?([\+\-]\d{2}:?\d{2})?$")
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Classes and functions
@@ -71,8 +71,12 b' def extract_dates(obj):'
71 71 elif isinstance(obj, (list, tuple)):
72 72 obj = [ extract_dates(o) for o in obj ]
73 73 elif isinstance(obj, basestring):
74 if ISO8601_PAT.match(obj):
75 obj = datetime.strptime(obj, ISO8601)
74 m = ISO8601_PAT.match(obj)
75 if m:
76 # FIXME: add actual timezone support
77 # this just drops the timezone info
78 notz = m.groups()[0]
79 obj = datetime.strptime(notz, ISO8601)
76 80 return obj
77 81
78 82 def squash_dates(obj):
@@ -84,13 +88,13 b' def squash_dates(obj):'
84 88 elif isinstance(obj, (list, tuple)):
85 89 obj = [ squash_dates(o) for o in obj ]
86 90 elif isinstance(obj, datetime):
87 obj = obj.strftime(ISO8601)
91 obj = obj.isoformat()
88 92 return obj
89 93
90 94 def date_default(obj):
91 95 """default function for packing datetime objects in JSON."""
92 96 if isinstance(obj, datetime):
93 return obj.strftime(ISO8601)
97 return obj.isoformat()
94 98 else:
95 99 raise TypeError("%r is not JSON serializable"%obj)
96 100
@@ -11,6 +11,7 b''
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13 # stdlib
14 import datetime
14 15 import json
15 16 from base64 import decodestring
16 17
@@ -19,6 +20,7 b' import nose.tools as nt'
19 20
20 21 # our own
21 22 from IPython.testing import decorators as dec
23 from IPython.utils import jsonutil, tz
22 24 from ..jsonutil import json_clean, encode_images
23 25 from ..py3compat import unicode_to_str, str_to_bytes
24 26
@@ -94,6 +96,33 b' def test_lambda():'
94 96 assert '<lambda>' in jc
95 97 json.dumps(jc)
96 98
99 def test_extract_dates():
100 timestamps = [
101 '2013-07-03T16:34:52.249482',
102 '2013-07-03T16:34:52.249482Z',
103 '2013-07-03T16:34:52.249482Z-0800',
104 '2013-07-03T16:34:52.249482Z+0800',
105 '2013-07-03T16:34:52.249482Z+08:00',
106 '2013-07-03T16:34:52.249482Z-08:00',
107 '2013-07-03T16:34:52.249482-0800',
108 '2013-07-03T16:34:52.249482+0800',
109 '2013-07-03T16:34:52.249482+08:00',
110 '2013-07-03T16:34:52.249482-08:00',
111 ]
112 extracted = jsonutil.extract_dates(timestamps)
113 ref = extracted[0]
114 for dt in extracted:
115 nt.assert_true(isinstance(dt, datetime.datetime))
116 nt.assert_equal(dt, ref)
117
118 def test_date_default():
119 data = dict(today=datetime.datetime.now(), utcnow=tz.utcnow())
120 jsondata = json.dumps(data, default=jsonutil.date_default)
121 nt.assert_in("+00", jsondata)
122 nt.assert_equal(jsondata.count("+00"), 1)
123 extracted = jsonutil.extract_dates(json.loads(jsondata))
124 for dt in extracted.values():
125 nt.assert_true(isinstance(dt, datetime.datetime))
97 126
98 127 def test_exception():
99 128 bad_dicts = [{1:'number', '1':'string'},
General Comments 0
You need to be logged in to leave comments. Login now