Merge "Support non-UTC timestamps in changes-since filter"

This commit is contained in:
Jenkins
2012-02-20 07:19:39 +00:00
committed by Gerrit Code Review
5 changed files with 132 additions and 7 deletions

View File

@@ -1528,7 +1528,7 @@ def instance_get_all_by_filters(context, filters):
filters = filters.copy() filters = filters.copy()
if 'changes-since' in filters: if 'changes-since' in filters:
changes_since = filters['changes-since'] changes_since = utils.normalize_time(filters['changes-since'])
query_prefix = query_prefix.\ query_prefix = query_prefix.\
filter(models.Instance.updated_at > changes_since) filter(models.Instance.updated_at > changes_since)

View File

@@ -21,6 +21,7 @@ import json
import urlparse import urlparse
import uuid import uuid
import iso8601
from lxml import etree from lxml import etree
import webob import webob
@@ -889,7 +890,8 @@ class ServersControllerTest(test.TestCase):
def fake_get_all(compute_self, context, search_opts=None): def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None) self.assertNotEqual(search_opts, None)
self.assertTrue('changes-since' in search_opts) self.assertTrue('changes-since' in search_opts)
changes_since = datetime.datetime(2011, 1, 24, 17, 8, 1) changes_since = datetime.datetime(2011, 1, 24, 17, 8, 1,
tzinfo=iso8601.iso8601.UTC)
self.assertEqual(search_opts['changes-since'], changes_since) self.assertEqual(search_opts['changes-since'], changes_since)
self.assertTrue('deleted' not in search_opts) self.assertTrue('deleted' not in search_opts)
return [fakes.stub_instance(100, uuid=server_uuid)] return [fakes.stub_instance(100, uuid=server_uuid)]

View File

@@ -15,13 +15,15 @@
# under the License. # under the License.
import __builtin__ import __builtin__
import mox
import datetime import datetime
import hashlib import hashlib
import os import os
import StringIO import StringIO
import tempfile import tempfile
import iso8601
import mox
import nova import nova
from nova import exception from nova import exception
from nova import flags from nova import flags
@@ -700,3 +702,108 @@ class DeprecationTest(test.TestCase):
h1 = utils.hash_file(flo) h1 = utils.hash_file(flo)
h2 = hashlib.sha1(data).hexdigest() h2 = hashlib.sha1(data).hexdigest()
self.assertEquals(h1, h2) self.assertEquals(h1, h2)
class Iso8601TimeTest(test.TestCase):
def _instaneous(self, timestamp, yr, mon, day, hr, min, sec, micro):
self.assertEquals(timestamp.year, yr)
self.assertEquals(timestamp.month, mon)
self.assertEquals(timestamp.day, day)
self.assertEquals(timestamp.hour, hr)
self.assertEquals(timestamp.minute, min)
self.assertEquals(timestamp.second, sec)
self.assertEquals(timestamp.microsecond, micro)
def _do_test(self, str, yr, mon, day, hr, min, sec, micro, shift):
DAY_SECONDS = 24 * 60 * 60
timestamp = utils.parse_isotime(str)
self._instaneous(timestamp, yr, mon, day, hr, min, sec, micro)
offset = timestamp.tzinfo.utcoffset(None)
self.assertEqual(offset.seconds + offset.days * DAY_SECONDS, shift)
def test_zulu(self):
str = '2012-02-14T20:53:07Z'
self._do_test(str, 2012, 02, 14, 20, 53, 7, 0, 0)
def test_zulu_micros(self):
str = '2012-02-14T20:53:07.123Z'
self._do_test(str, 2012, 02, 14, 20, 53, 7, 123000, 0)
def test_offset_east(self):
str = '2012-02-14T20:53:07+04:30'
offset = 4.5 * 60 * 60
self._do_test(str, 2012, 02, 14, 20, 53, 7, 0, offset)
def test_offset_east_micros(self):
str = '2012-02-14T20:53:07.42+04:30'
offset = 4.5 * 60 * 60
self._do_test(str, 2012, 02, 14, 20, 53, 7, 420000, offset)
def test_offset_west(self):
str = '2012-02-14T20:53:07-05:30'
offset = -5.5 * 60 * 60
self._do_test(str, 2012, 02, 14, 20, 53, 7, 0, offset)
def test_offset_west_micros(self):
str = '2012-02-14T20:53:07.654321-05:30'
offset = -5.5 * 60 * 60
self._do_test(str, 2012, 02, 14, 20, 53, 7, 654321, offset)
def test_compare(self):
zulu = utils.parse_isotime('2012-02-14T20:53:07')
east = utils.parse_isotime('2012-02-14T20:53:07-01:00')
west = utils.parse_isotime('2012-02-14T20:53:07+01:00')
self.assertTrue(east > west)
self.assertTrue(east > zulu)
self.assertTrue(zulu > west)
def test_compare_micros(self):
zulu = utils.parse_isotime('2012-02-14T20:53:07.6544')
east = utils.parse_isotime('2012-02-14T19:53:07.654321-01:00')
west = utils.parse_isotime('2012-02-14T21:53:07.655+01:00')
self.assertTrue(east < west)
self.assertTrue(east < zulu)
self.assertTrue(zulu < west)
def test_zulu_roundtrip(self):
str = '2012-02-14T20:53:07Z'
zulu = utils.parse_isotime(str)
self.assertEquals(zulu.tzinfo, iso8601.iso8601.UTC)
self.assertEquals(utils.isotime(zulu), str)
def test_east_roundtrip(self):
str = '2012-02-14T20:53:07-07:00'
east = utils.parse_isotime(str)
self.assertEquals(east.tzinfo.tzname(None), '-07:00')
self.assertEquals(utils.isotime(east), str)
def test_west_roundtrip(self):
str = '2012-02-14T20:53:07+11:30'
west = utils.parse_isotime(str)
self.assertEquals(west.tzinfo.tzname(None), '+11:30')
self.assertEquals(utils.isotime(west), str)
def test_now_roundtrip(self):
str = utils.isotime()
now = utils.parse_isotime(str)
self.assertEquals(now.tzinfo, iso8601.iso8601.UTC)
self.assertEquals(utils.isotime(now), str)
def test_zulu_normalize(self):
str = '2012-02-14T20:53:07Z'
zulu = utils.parse_isotime(str)
normed = utils.normalize_time(zulu)
self._instaneous(normed, 2012, 2, 14, 20, 53, 07, 0)
def test_east_normalize(self):
str = '2012-02-14T20:53:07-07:00'
east = utils.parse_isotime(str)
normed = utils.normalize_time(east)
self._instaneous(normed, 2012, 2, 15, 03, 53, 07, 0)
def test_west_normalize(self):
str = '2012-02-14T20:53:07+21:00'
west = utils.parse_isotime(str)
normed = utils.normalize_time(west)
self._instaneous(normed, 2012, 2, 13, 23, 53, 07, 0)

View File

@@ -44,6 +44,7 @@ from eventlet import event
from eventlet import greenthread from eventlet import greenthread
from eventlet import semaphore from eventlet import semaphore
from eventlet.green import subprocess from eventlet.green import subprocess
import iso8601
import netaddr import netaddr
from nova import exception from nova import exception
@@ -53,7 +54,7 @@ from nova.openstack.common import cfg
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
ISO_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" ISO_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
@@ -534,13 +535,27 @@ def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT):
def isotime(at=None): def isotime(at=None):
"""Returns iso formatted utcnow.""" """Stringify time in ISO 8601 format"""
return strtime(at, ISO_TIME_FORMAT) if not at:
at = datetime.datetime.utcnow()
str = at.strftime(ISO_TIME_FORMAT)
tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC'
str += ('Z' if tz == 'UTC' else tz)
return str
def parse_isotime(timestr): def parse_isotime(timestr):
"""Turn an iso formatted time back into a datetime.""" """Turn an iso formatted time back into a datetime."""
return parse_strtime(timestr, ISO_TIME_FORMAT) try:
return iso8601.parse_date(timestr)
except (iso8601.ParseError, TypeError) as e:
raise ValueError(e.message)
def normalize_time(timestamp):
"""Normalize time in arbitrary timezone to UTC"""
offset = timestamp.utcoffset()
return timestamp.replace(tzinfo=None) - offset if offset else timestamp
def parse_mailmap(mailmap='.mailmap'): def parse_mailmap(mailmap='.mailmap'):

View File

@@ -33,3 +33,4 @@ paramiko
feedparser feedparser
pycrypto pycrypto
Babel>=0.9.6 Babel>=0.9.6
iso8601>=0.1.4