mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 12:33:40 +00:00
Clean up timestamps.py and add a test.
This commit is contained in:
@@ -15,7 +15,6 @@ from django.conf import settings
|
|||||||
|
|
||||||
from analytics.models import RealmCount, UserCount
|
from analytics.models import RealmCount, UserCount
|
||||||
from analytics.lib.counts import COUNT_STATS, logger, process_count_stat
|
from analytics.lib.counts import COUNT_STATS, logger, process_count_stat
|
||||||
from zerver.lib.timestamp import datetime_to_string, is_timezone_aware
|
|
||||||
from zerver.models import UserProfile, Message
|
from zerver.models import UserProfile, Message
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -30,7 +29,7 @@ class Command(BaseCommand):
|
|||||||
parser.add_argument('--time', '-t',
|
parser.add_argument('--time', '-t',
|
||||||
type=str,
|
type=str,
|
||||||
help='Update stat tables from current state to --time. Defaults to the current time.',
|
help='Update stat tables from current state to --time. Defaults to the current time.',
|
||||||
default=datetime_to_string(timezone.now()))
|
default=timezone.now().isoformat())
|
||||||
parser.add_argument('--utc',
|
parser.add_argument('--utc',
|
||||||
type=bool,
|
type=bool,
|
||||||
help="Interpret --time in UTC.",
|
help="Interpret --time in UTC.",
|
||||||
@@ -61,7 +60,7 @@ class Command(BaseCommand):
|
|||||||
if options['utc']:
|
if options['utc']:
|
||||||
fill_to_time = fill_to_time.replace(tzinfo=timezone.utc)
|
fill_to_time = fill_to_time.replace(tzinfo=timezone.utc)
|
||||||
|
|
||||||
if not (is_timezone_aware(fill_to_time)):
|
if fill_to_time.tzinfo is None:
|
||||||
raise ValueError("--time must be timezone aware. Maybe you meant to use the --utc option?")
|
raise ValueError("--time must be timezone aware. Maybe you meant to use the --utc option?")
|
||||||
|
|
||||||
logger.info("Starting updating analytics counts through %s" % (fill_to_time,))
|
logger.info("Starting updating analytics counts through %s" % (fill_to_time,))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from django.utils import timezone
|
|||||||
|
|
||||||
from zerver.models import Realm, UserProfile, Stream, Recipient
|
from zerver.models import Realm, UserProfile, Stream, Recipient
|
||||||
from zerver.lib.str_utils import ModelReprMixin
|
from zerver.lib.str_utils import ModelReprMixin
|
||||||
from zerver.lib.timestamp import datetime_to_UTC, floor_to_day
|
from zerver.lib.timestamp import floor_to_day
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ class FillState(ModelReprMixin, models.Model):
|
|||||||
def installation_epoch():
|
def installation_epoch():
|
||||||
# type: () -> datetime.datetime
|
# type: () -> datetime.datetime
|
||||||
earliest_realm_creation = Realm.objects.aggregate(models.Min('date_created'))['date_created__min']
|
earliest_realm_creation = Realm.objects.aggregate(models.Min('date_created'))['date_created__min']
|
||||||
return floor_to_day(datetime_to_UTC(earliest_realm_creation))
|
return floor_to_day(earliest_realm_creation)
|
||||||
|
|
||||||
def last_successful_fill(property):
|
def last_successful_fill(property):
|
||||||
# type: (str) -> Optional[datetime.datetime]
|
# type: (str) -> Optional[datetime.datetime]
|
||||||
|
|||||||
@@ -4,37 +4,27 @@ import datetime
|
|||||||
import calendar
|
import calendar
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
def is_timezone_aware(datetime_object):
|
def floor_to_hour(dt):
|
||||||
# type: (datetime.datetime) -> bool
|
|
||||||
return datetime_object.tzinfo is not None
|
|
||||||
|
|
||||||
def datetime_to_UTC(datetime_object):
|
|
||||||
# type: (datetime.datetime) -> datetime.datetime
|
# type: (datetime.datetime) -> datetime.datetime
|
||||||
if is_timezone_aware(datetime_object):
|
return datetime.datetime(*dt.timetuple()[:4]) \
|
||||||
return datetime_object.astimezone(timezone.utc)
|
.replace(tzinfo=dt.tzinfo)
|
||||||
return datetime_object.replace(tzinfo=timezone.utc)
|
|
||||||
|
|
||||||
def floor_to_hour(datetime_object):
|
def floor_to_day(dt):
|
||||||
# type: (datetime.datetime) -> datetime.datetime
|
# type: (datetime.datetime) -> datetime.datetime
|
||||||
return datetime.datetime(*datetime_object.timetuple()[:4]) \
|
return datetime.datetime(*dt.timetuple()[:3]) \
|
||||||
.replace(tzinfo=datetime_object.tzinfo)
|
.replace(tzinfo=dt.tzinfo)
|
||||||
|
|
||||||
def floor_to_day(datetime_object):
|
def ceiling_to_hour(dt):
|
||||||
# type: (datetime.datetime) -> datetime.datetime
|
# type: (datetime.datetime) -> datetime.datetime
|
||||||
return datetime.datetime(*datetime_object.timetuple()[:3]) \
|
floor = floor_to_hour(dt)
|
||||||
.replace(tzinfo=datetime_object.tzinfo)
|
if floor == dt:
|
||||||
|
|
||||||
def ceiling_to_hour(datetime_object):
|
|
||||||
# type: (datetime.datetime) -> datetime.datetime
|
|
||||||
floor = floor_to_hour(datetime_object)
|
|
||||||
if floor == datetime_object:
|
|
||||||
return floor
|
return floor
|
||||||
return floor + datetime.timedelta(hours=1)
|
return floor + datetime.timedelta(hours=1)
|
||||||
|
|
||||||
def ceiling_to_day(datetime_object):
|
def ceiling_to_day(dt):
|
||||||
# type: (datetime.datetime) -> datetime.datetime
|
# type: (datetime.datetime) -> datetime.datetime
|
||||||
floor = floor_to_day(datetime_object)
|
floor = floor_to_day(dt)
|
||||||
if floor == datetime_object:
|
if floor == dt:
|
||||||
return floor
|
return floor
|
||||||
return floor + datetime.timedelta(days=1)
|
return floor + datetime.timedelta(days=1)
|
||||||
|
|
||||||
@@ -42,12 +32,11 @@ def timestamp_to_datetime(timestamp):
|
|||||||
# type: (float) -> datetime.datetime
|
# type: (float) -> datetime.datetime
|
||||||
return datetime.datetime.fromtimestamp(float(timestamp), tz=timezone.utc)
|
return datetime.datetime.fromtimestamp(float(timestamp), tz=timezone.utc)
|
||||||
|
|
||||||
def datetime_to_timestamp(datetime_object):
|
class TimezoneNotUTCException(Exception):
|
||||||
# type: (datetime.datetime) -> int
|
pass
|
||||||
return calendar.timegm(datetime_object.timetuple())
|
|
||||||
|
|
||||||
def datetime_to_string(datetime_object):
|
def datetime_to_timestamp(dt):
|
||||||
# type: (datetime.datetime) -> str
|
# type: (datetime.datetime) -> int
|
||||||
assert is_timezone_aware(datetime_object)
|
if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) != timezone.utc.utcoffset(dt):
|
||||||
date_string = datetime_object.strftime('%Y-%m-%d %H:%M:%S%z')
|
raise TimezoneNotUTCException("Datetime %s to be converted does not have a UTC timezone." % (dt,))
|
||||||
return date_string
|
return calendar.timegm(dt.timetuple())
|
||||||
|
|||||||
31
zerver/tests/test_timestamp.py
Normal file
31
zerver/tests/test_timestamp.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
|
from zerver.lib.timestamp import floor_to_hour, floor_to_day, ceiling_to_hour, \
|
||||||
|
ceiling_to_day, timestamp_to_datetime, datetime_to_timestamp, \
|
||||||
|
TimezoneNotUTCException
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from dateutil import parser
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
from six.moves import zip
|
||||||
|
|
||||||
|
class TestTimestamp(ZulipTestCase):
|
||||||
|
def test_datetime_and_timestamp_conversions(self):
|
||||||
|
# type: () -> None
|
||||||
|
timestamp = 1483228800
|
||||||
|
for dt in [
|
||||||
|
parser.parse('2017-01-01 00:00:00.123 UTC'),
|
||||||
|
parser.parse('2017-01-01 00:00:00.123').replace(tzinfo=timezone.utc),
|
||||||
|
parser.parse('2017-01-01 00:00:00.123').replace(tzinfo=pytz.utc)]:
|
||||||
|
self.assertEqual(timestamp_to_datetime(timestamp), dt-timedelta(microseconds=123000))
|
||||||
|
self.assertEqual(datetime_to_timestamp(dt), timestamp)
|
||||||
|
|
||||||
|
for dt in [
|
||||||
|
parser.parse('2017-01-01 00:00:00.123+01:00'),
|
||||||
|
parser.parse('2017-01-01 00:00:00.123')]:
|
||||||
|
with self.assertRaises(TimezoneNotUTCException):
|
||||||
|
datetime_to_timestamp(dt)
|
||||||
Reference in New Issue
Block a user