##// 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 from .nbmanager import NotebookManager
26 from .nbmanager import NotebookManager
27 from IPython.nbformat import current
27 from IPython.nbformat import current
28 from IPython.utils.traitlets import Unicode, Instance
28 from IPython.utils.traitlets import Unicode, Instance
29
29 from IPython.utils import tz
30
30
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 # Classes
32 # Classes
@@ -98,7 +98,7 b' class AzureNotebookManager(NotebookManager):'
98 raise web.HTTPError(500, u'Unreadable JSON notebook.')
98 raise web.HTTPError(500, u'Unreadable JSON notebook.')
99 # Todo: The last modified should actually be saved in the notebook document.
99 # Todo: The last modified should actually be saved in the notebook document.
100 # We are just using the current datetime until that is implemented.
100 # We are just using the current datetime until that is implemented.
101 last_modified = datetime.datetime.utcnow()
101 last_modified = tz.utcnow()
102 return last_modified, nb
102 return last_modified, nb
103
103
104 def write_notebook_object(self, nb, notebook_id=None):
104 def write_notebook_object(self, nb, notebook_id=None):
@@ -28,6 +28,7 b' from tornado import web'
28 from .nbmanager import NotebookManager
28 from .nbmanager import NotebookManager
29 from IPython.nbformat import current
29 from IPython.nbformat import current
30 from IPython.utils.traitlets import Unicode, Dict, Bool, TraitError
30 from IPython.utils.traitlets import Unicode, Dict, Bool, TraitError
31 from IPython.utils import tz
31
32
32 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
33 # Classes
34 # Classes
@@ -139,7 +140,7 b' class FileNotebookManager(NotebookManager):'
139 def read_notebook_object_from_path(self, path):
140 def read_notebook_object_from_path(self, path):
140 """read a notebook object from a path"""
141 """read a notebook object from a path"""
141 info = os.stat(path)
142 info = os.stat(path)
142 last_modified = datetime.datetime.utcfromtimestamp(info.st_mtime)
143 last_modified = tz.utcfromtimestamp(info.st_mtime)
143 with open(path,'r') as f:
144 with open(path,'r') as f:
144 s = f.read()
145 s = f.read()
145 try:
146 try:
@@ -281,7 +282,7 b' class FileNotebookManager(NotebookManager):'
281 """construct the info dict for a given checkpoint"""
282 """construct the info dict for a given checkpoint"""
282 path = self.get_checkpoint_path(notebook_id, checkpoint_id)
283 path = self.get_checkpoint_path(notebook_id, checkpoint_id)
283 stats = os.stat(path)
284 stats = os.stat(path)
284 last_modified = datetime.datetime.utcfromtimestamp(stats.st_mtime)
285 last_modified = tz.utcfromtimestamp(stats.st_mtime)
285 info = dict(
286 info = dict(
286 checkpoint_id = checkpoint_id,
287 checkpoint_id = checkpoint_id,
287 last_modified = last_modified,
288 last_modified = last_modified,
@@ -33,7 +33,7 b" next_attr_name = '__next__' if py3compat.PY3 else 'next'"
33
33
34 # timestamp formats
34 # timestamp formats
35 ISO8601="%Y-%m-%dT%H:%M:%S.%f"
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 # Classes and functions
39 # Classes and functions
@@ -71,8 +71,12 b' def extract_dates(obj):'
71 elif isinstance(obj, (list, tuple)):
71 elif isinstance(obj, (list, tuple)):
72 obj = [ extract_dates(o) for o in obj ]
72 obj = [ extract_dates(o) for o in obj ]
73 elif isinstance(obj, basestring):
73 elif isinstance(obj, basestring):
74 if ISO8601_PAT.match(obj):
74 m = ISO8601_PAT.match(obj)
75 obj = datetime.strptime(obj, ISO8601)
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 return obj
80 return obj
77
81
78 def squash_dates(obj):
82 def squash_dates(obj):
@@ -84,13 +88,13 b' def squash_dates(obj):'
84 elif isinstance(obj, (list, tuple)):
88 elif isinstance(obj, (list, tuple)):
85 obj = [ squash_dates(o) for o in obj ]
89 obj = [ squash_dates(o) for o in obj ]
86 elif isinstance(obj, datetime):
90 elif isinstance(obj, datetime):
87 obj = obj.strftime(ISO8601)
91 obj = obj.isoformat()
88 return obj
92 return obj
89
93
90 def date_default(obj):
94 def date_default(obj):
91 """default function for packing datetime objects in JSON."""
95 """default function for packing datetime objects in JSON."""
92 if isinstance(obj, datetime):
96 if isinstance(obj, datetime):
93 return obj.strftime(ISO8601)
97 return obj.isoformat()
94 else:
98 else:
95 raise TypeError("%r is not JSON serializable"%obj)
99 raise TypeError("%r is not JSON serializable"%obj)
96
100
@@ -11,6 +11,7 b''
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # stdlib
13 # stdlib
14 import datetime
14 import json
15 import json
15 from base64 import decodestring
16 from base64 import decodestring
16
17
@@ -19,6 +20,7 b' import nose.tools as nt'
19
20
20 # our own
21 # our own
21 from IPython.testing import decorators as dec
22 from IPython.testing import decorators as dec
23 from IPython.utils import jsonutil, tz
22 from ..jsonutil import json_clean, encode_images
24 from ..jsonutil import json_clean, encode_images
23 from ..py3compat import unicode_to_str, str_to_bytes
25 from ..py3compat import unicode_to_str, str_to_bytes
24
26
@@ -94,6 +96,33 b' def test_lambda():'
94 assert '<lambda>' in jc
96 assert '<lambda>' in jc
95 json.dumps(jc)
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 def test_exception():
127 def test_exception():
99 bad_dicts = [{1:'number', '1':'string'},
128 bad_dicts = [{1:'number', '1':'string'},
General Comments 0
You need to be logged in to leave comments. Login now