mirror of https://github.com/zulip/zulip.git
timezone: Use standard library datetime.timezone.utc consistently.
datetime.timezone is available in Python ≥ 3.2. This also lets us remove a pytz dependency from the PostgreSQL scripts. Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
29b8e11e20
commit
1f565a9f41
|
@ -2,14 +2,13 @@ import datetime
|
|||
from typing import Any, Dict
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandParser
|
||||
from django.utils.timezone import utc
|
||||
|
||||
from zerver.lib.statistics import seconds_usage_between
|
||||
from zerver.models import UserProfile
|
||||
|
||||
|
||||
def analyze_activity(options: Dict[str, Any]) -> None:
|
||||
day_start = datetime.datetime.strptime(options["date"], "%Y-%m-%d").replace(tzinfo=utc)
|
||||
day_start = datetime.datetime.strptime(options["date"], "%Y-%m-%d").replace(tzinfo=datetime.timezone.utc)
|
||||
day_end = day_start + datetime.timedelta(days=options["duration"])
|
||||
|
||||
user_profile_query = UserProfile.objects.all()
|
||||
|
|
|
@ -2,12 +2,12 @@ import os
|
|||
import time
|
||||
from argparse import ArgumentParser
|
||||
from typing import Any, Dict
|
||||
from datetime import timezone
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils.dateparse import parse_datetime
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, logger, process_count_stat
|
||||
from scripts.lib.zulip_tools import ENDC, WARNING
|
||||
|
@ -60,11 +60,11 @@ class Command(BaseCommand):
|
|||
|
||||
fill_to_time = parse_datetime(options['time'])
|
||||
if options['utc']:
|
||||
fill_to_time = fill_to_time.replace(tzinfo=timezone_utc)
|
||||
fill_to_time = fill_to_time.replace(tzinfo=timezone.utc)
|
||||
if fill_to_time.tzinfo is None:
|
||||
raise ValueError("--time must be timezone aware. Maybe you meant to use the --utc option?")
|
||||
|
||||
fill_to_time = floor_to_hour(fill_to_time.astimezone(timezone_utc))
|
||||
fill_to_time = floor_to_hour(fill_to_time.astimezone(timezone.utc))
|
||||
|
||||
if options['stat'] is not None:
|
||||
stats = [COUNT_STATS[options['stat']]]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Dict, List, Optional, Tuple, Type
|
||||
|
||||
from unittest import mock
|
||||
|
@ -8,7 +8,6 @@ from django.db import models
|
|||
from django.db.models import Sum
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, CountStat, get_count_stats, \
|
||||
DependentCountStat, LoggingCountStat, do_aggregate_to_summary_table, \
|
||||
|
@ -33,7 +32,7 @@ class AnalyticsTestCase(TestCase):
|
|||
MINUTE = timedelta(seconds = 60)
|
||||
HOUR = MINUTE * 60
|
||||
DAY = HOUR * 24
|
||||
TIME_ZERO = datetime(1988, 3, 14).replace(tzinfo=timezone_utc)
|
||||
TIME_ZERO = datetime(1988, 3, 14, tzinfo=timezone.utc)
|
||||
TIME_LAST_HOUR = TIME_ZERO - HOUR
|
||||
|
||||
def setUp(self) -> None:
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import List, Optional
|
||||
|
||||
from unittest import mock
|
||||
from django.utils.timezone import utc
|
||||
from django.http import HttpResponse
|
||||
import ujson
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
@ -607,8 +606,8 @@ class TestGetChartDataHelpers(ZulipTestCase):
|
|||
# the only function that uses it at the moment
|
||||
def test_last_successful_fill(self) -> None:
|
||||
self.assertIsNone(last_successful_fill('non-existant'))
|
||||
a_time = datetime(2016, 3, 14, 19).replace(tzinfo=utc)
|
||||
one_hour_before = datetime(2016, 3, 14, 18).replace(tzinfo=utc)
|
||||
a_time = datetime(2016, 3, 14, 19, tzinfo=timezone.utc)
|
||||
one_hour_before = datetime(2016, 3, 14, 18, tzinfo=timezone.utc)
|
||||
fillstate = FillState.objects.create(property='property', end_time=a_time,
|
||||
state=FillState.DONE)
|
||||
self.assertEqual(last_successful_fill('property'), a_time)
|
||||
|
@ -631,9 +630,9 @@ class TestTimeRange(ZulipTestCase):
|
|||
HOUR = timedelta(hours=1)
|
||||
DAY = timedelta(days=1)
|
||||
|
||||
a_time = datetime(2016, 3, 14, 22, 59).replace(tzinfo=utc)
|
||||
floor_hour = datetime(2016, 3, 14, 22).replace(tzinfo=utc)
|
||||
floor_day = datetime(2016, 3, 14).replace(tzinfo=utc)
|
||||
a_time = datetime(2016, 3, 14, 22, 59, tzinfo=timezone.utc)
|
||||
floor_hour = datetime(2016, 3, 14, 22, tzinfo=timezone.utc)
|
||||
floor_day = datetime(2016, 3, 14, tzinfo=timezone.utc)
|
||||
|
||||
# test start == end
|
||||
self.assertEqual(time_range(a_time, a_time, CountStat.HOUR, None), [])
|
||||
|
|
|
@ -4,7 +4,7 @@ import re
|
|||
import time
|
||||
import urllib
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from decimal import Decimal
|
||||
|
||||
from typing import Any, Callable, Dict, List, \
|
||||
|
@ -18,7 +18,7 @@ from django.db.models.query import QuerySet
|
|||
from django.http import HttpRequest, HttpResponse, HttpResponseNotFound
|
||||
from django.shortcuts import render
|
||||
from django.template import loader
|
||||
from django.utils.timezone import now as timezone_now, utc as timezone_utc
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.timesince import timesince
|
||||
from django.core.validators import URLValidator
|
||||
|
@ -253,7 +253,7 @@ def get_chart_data(request: HttpRequest, user_profile: UserProfile, chart_name:
|
|||
start = realm.date_created
|
||||
if end is None:
|
||||
end = max(last_successful_fill(stat.property) or
|
||||
datetime.min.replace(tzinfo=timezone_utc) for stat in stats)
|
||||
datetime.min.replace(tzinfo=timezone.utc) for stat in stats)
|
||||
|
||||
if start > end and (timezone_now() - start > MAX_TIME_FOR_FULL_ANALYTICS_GENERATION):
|
||||
logging.warning("User from realm %s attempted to access /stats, but the computed "
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from decimal import Decimal
|
||||
from functools import wraps
|
||||
from unittest.mock import Mock, patch
|
||||
|
@ -14,7 +14,6 @@ import responses
|
|||
from django.core import signing
|
||||
from django.urls.resolvers import get_resolver
|
||||
from django.http import HttpResponse
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
from django.conf import settings
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
|
@ -265,9 +264,9 @@ class StripeTestCase(ZulipTestCase):
|
|||
self.signed_seat_count, self.salt = sign_string(str(self.seat_count))
|
||||
# Choosing dates with corresponding timestamps below 1500000000 so that they are
|
||||
# not caught by our timestamp normalization regex in normalize_fixture_data
|
||||
self.now = datetime(2012, 1, 2, 3, 4, 5).replace(tzinfo=timezone_utc)
|
||||
self.next_month = datetime(2012, 2, 2, 3, 4, 5).replace(tzinfo=timezone_utc)
|
||||
self.next_year = datetime(2013, 1, 2, 3, 4, 5).replace(tzinfo=timezone_utc)
|
||||
self.now = datetime(2012, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
|
||||
self.next_month = datetime(2012, 2, 2, 3, 4, 5, tzinfo=timezone.utc)
|
||||
self.next_year = datetime(2013, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
|
||||
|
||||
def get_signed_seat_count_from_response(self, response: HttpResponse) -> Optional[str]:
|
||||
match = re.search(r'name=\"signed_seat_count\" value=\"(.+)\"', response.content.decode("utf-8"))
|
||||
|
@ -1552,24 +1551,24 @@ class RequiresBillingAccessTest(ZulipTestCase):
|
|||
|
||||
class BillingHelpersTest(ZulipTestCase):
|
||||
def test_next_month(self) -> None:
|
||||
anchor = datetime(2019, 12, 31, 1, 2, 3).replace(tzinfo=timezone_utc)
|
||||
anchor = datetime(2019, 12, 31, 1, 2, 3, tzinfo=timezone.utc)
|
||||
period_boundaries = [
|
||||
anchor,
|
||||
datetime(2020, 1, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 1, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
# Test that this is the 28th even during leap years
|
||||
datetime(2020, 2, 28, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 3, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 4, 30, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 5, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 6, 30, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 7, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 8, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 9, 30, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 10, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 11, 30, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2020, 12, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2021, 1, 31, 1, 2, 3).replace(tzinfo=timezone_utc),
|
||||
datetime(2021, 2, 28, 1, 2, 3).replace(tzinfo=timezone_utc)]
|
||||
datetime(2020, 2, 28, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 3, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 4, 30, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 5, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 6, 30, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 7, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 8, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 9, 30, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 10, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 11, 30, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2020, 12, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2021, 1, 31, 1, 2, 3, tzinfo=timezone.utc),
|
||||
datetime(2021, 2, 28, 1, 2, 3, tzinfo=timezone.utc)]
|
||||
with self.assertRaises(AssertionError):
|
||||
add_months(anchor, -1)
|
||||
# Explicitly test add_months for each value of MAX_DAY_FOR_MONTH and
|
||||
|
@ -1586,9 +1585,9 @@ class BillingHelpersTest(ZulipTestCase):
|
|||
|
||||
def test_compute_plan_parameters(self) -> None:
|
||||
# TODO: test rounding down microseconds
|
||||
anchor = datetime(2019, 12, 31, 1, 2, 3).replace(tzinfo=timezone_utc)
|
||||
month_later = datetime(2020, 1, 31, 1, 2, 3).replace(tzinfo=timezone_utc)
|
||||
year_later = datetime(2020, 12, 31, 1, 2, 3).replace(tzinfo=timezone_utc)
|
||||
anchor = datetime(2019, 12, 31, 1, 2, 3, tzinfo=timezone.utc)
|
||||
month_later = datetime(2020, 1, 31, 1, 2, 3, tzinfo=timezone.utc)
|
||||
year_later = datetime(2020, 12, 31, 1, 2, 3, tzinfo=timezone.utc)
|
||||
test_cases = [
|
||||
# TODO test with Decimal(85), not 85
|
||||
# TODO fix the mypy error by specifying the exact type
|
||||
|
|
|
@ -153,19 +153,19 @@ Python allows datetime objects to not have an associated timezone, which can
|
|||
cause time-related bugs that are hard to catch with a test suite, or bugs
|
||||
that only show up during daylight savings time.
|
||||
|
||||
Good ways to make timezone-aware datetimes are below. We import `timezone`
|
||||
functions as `from django.utils.timezone import now as timezone_now` and
|
||||
`from django.utils.timezone import utc as timezone_utc`.
|
||||
Good ways to make timezone-aware datetimes are below. We import timezone
|
||||
libraries as `from datetime import datetime, timezone` and `from
|
||||
django.utils.timezone import now as timezone_now`.
|
||||
|
||||
Use:
|
||||
* `timezone_now()` to get a datetime when Django is available, such as
|
||||
in `zerver/`.
|
||||
* `datetime.now(tz=pytz.utc)` when Django is not available, such as
|
||||
* `datetime.now(tz=timezone.utc)` when Django is not available, such as
|
||||
for bots and scripts.
|
||||
* `datetime.fromtimestamp(timestamp, tz=timezone_utc)` if creating a
|
||||
* `datetime.fromtimestamp(timestamp, tz=timezone.utc)` if creating a
|
||||
datetime from a timestamp. This is also available as
|
||||
`zerver.lib.timestamp.timestamp_to_datetime`.
|
||||
* `datetime.strptime(date_string, format).replace(tzinfo=timezone_utc)` if
|
||||
* `datetime.strptime(date_string, format).replace(tzinfo=timezone.utc)` if
|
||||
creating a datetime from a formatted string that is in UTC.
|
||||
|
||||
Idioms that result in timezone-naive datetimes, and should be avoided, are
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import dateutil.parser
|
||||
import pytz
|
||||
|
||||
states = {
|
||||
"OK": 0,
|
||||
|
@ -28,7 +27,7 @@ try:
|
|||
except OSError:
|
||||
report('UNKNOWN', 'could not determine completion time of last Postgres backup')
|
||||
|
||||
if datetime.now(tz=pytz.utc) - last_backup > timedelta(hours=25):
|
||||
if datetime.now(tz=timezone.utc) - last_backup > timedelta(hours=25):
|
||||
report('CRITICAL', 'last Postgres backup completed more than 25 hours ago: %s' % (last_backup,))
|
||||
|
||||
report('OK', 'last Postgres backup completed less than 25 hours ago: %s' % (last_backup,))
|
||||
|
|
|
@ -7,9 +7,8 @@ import shlex
|
|||
import subprocess
|
||||
import logging
|
||||
import dateutil.parser
|
||||
import pytz
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Dict, List
|
||||
|
||||
logging.Formatter.converter = time.gmtime
|
||||
|
@ -48,7 +47,7 @@ if len(pg_data_paths) != 1:
|
|||
pg_data_path = pg_data_paths[0]
|
||||
run(['env-wal-e', 'backup-push', pg_data_path])
|
||||
|
||||
now = datetime.now(tz=pytz.utc)
|
||||
now = datetime.now(tz=timezone.utc)
|
||||
with open('/var/lib/nagios_state/last_postgres_backup', 'w') as f:
|
||||
f.write(now.isoformat())
|
||||
f.write("\n")
|
||||
|
|
|
@ -15,10 +15,7 @@ class zulip::postgres_common {
|
|||
# Postgres Nagios check plugin
|
||||
'check-postgres',
|
||||
# Python modules used in our monitoring/worker threads
|
||||
'python3-tz', # TODO: use a virtualenv instead
|
||||
'python-tz', # TODO: use a virtualenv instead
|
||||
'python3-dateutil', # TODO: use a virtualenv instead
|
||||
'python-dateutil', # TODO: use a virtualenv instead
|
||||
]
|
||||
$postgres_user_reqs = [
|
||||
Package[$postgresql],
|
||||
|
@ -39,12 +36,8 @@ class zulip::postgres_common {
|
|||
# https://bucardo.org/check_postgres/
|
||||
# 'check-postgres', # TODO
|
||||
]
|
||||
exec {'pip2_deps':
|
||||
# Python modules used in our monitoring/worker threads
|
||||
command => '/usr/bin/pip2 install pytz python-dateutil'
|
||||
}
|
||||
exec {'pip3_deps':
|
||||
command => 'python3 -m pip install pytz python-dateutil'
|
||||
command => 'python3 -m pip install python-dateutil'
|
||||
}
|
||||
group { 'ssl-cert':
|
||||
ensure => present,
|
||||
|
|
|
@ -3,7 +3,6 @@ from typing import Any, Dict, List, Set, Tuple, Union
|
|||
from collections import defaultdict
|
||||
import datetime
|
||||
import logging
|
||||
import pytz
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
@ -168,7 +167,7 @@ def handle_digest_email(user_profile_id: int, cutoff: float,
|
|||
user_profile = get_user_profile_by_id(user_profile_id)
|
||||
|
||||
# Convert from epoch seconds to a datetime object.
|
||||
cutoff_date = datetime.datetime.fromtimestamp(int(cutoff), tz=pytz.utc)
|
||||
cutoff_date = datetime.datetime.fromtimestamp(int(cutoff), tz=datetime.timezone.utc)
|
||||
|
||||
context = common_context(user_profile)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from bs4 import BeautifulSoup
|
|||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from django.db.models import Max
|
||||
from django.utils.timezone import utc as timezone_utc, now as timezone_now
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple, \
|
||||
Iterable, cast
|
||||
|
||||
|
@ -109,7 +109,7 @@ def fix_datetime_fields(data: TableData, table: TableName) -> None:
|
|||
for item in data[table]:
|
||||
for field_name in DATE_FIELDS[table]:
|
||||
if item[field_name] is not None:
|
||||
item[field_name] = datetime.datetime.fromtimestamp(item[field_name], tz=timezone_utc)
|
||||
item[field_name] = datetime.datetime.fromtimestamp(item[field_name], tz=datetime.timezone.utc)
|
||||
|
||||
def fix_upload_links(data: TableData, message_table: TableName) -> None:
|
||||
"""
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
# System documented in https://zulip.readthedocs.io/en/latest/subsystems/logging.html
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import threading
|
||||
import traceback
|
||||
from typing import Optional, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from logging import Logger
|
||||
|
@ -28,7 +27,7 @@ class _RateLimitFilter:
|
|||
Adapted from https://djangosnippets.org/snippets/2242/.
|
||||
|
||||
"""
|
||||
last_error = datetime.min.replace(tzinfo=timezone_utc)
|
||||
last_error = datetime.min.replace(tzinfo=timezone.utc)
|
||||
# This thread-local variable is used to detect recursive
|
||||
# exceptions during exception handling (primarily intended for
|
||||
# when accessing the shared cache throws an exception).
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
import datetime
|
||||
import calendar
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
class TimezoneNotUTCException(Exception):
|
||||
pass
|
||||
|
||||
def verify_UTC(dt: datetime.datetime) -> None:
|
||||
if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) != timezone_utc.utcoffset(dt):
|
||||
if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) != datetime.timezone.utc.utcoffset(dt):
|
||||
raise TimezoneNotUTCException("Datetime %s does not have a UTC timezone." % (dt,))
|
||||
|
||||
def convert_to_UTC(dt: datetime.datetime) -> datetime.datetime:
|
||||
if dt.tzinfo is None:
|
||||
return dt.replace(tzinfo=timezone_utc)
|
||||
return dt.astimezone(timezone_utc)
|
||||
return dt.replace(tzinfo=datetime.timezone.utc)
|
||||
return dt.astimezone(datetime.timezone.utc)
|
||||
|
||||
def floor_to_hour(dt: datetime.datetime) -> datetime.datetime:
|
||||
verify_UTC(dt)
|
||||
return datetime.datetime(*dt.timetuple()[:4]) \
|
||||
.replace(tzinfo=timezone_utc)
|
||||
return datetime.datetime(*dt.timetuple()[:4], tzinfo=datetime.timezone.utc)
|
||||
|
||||
def floor_to_day(dt: datetime.datetime) -> datetime.datetime:
|
||||
verify_UTC(dt)
|
||||
return datetime.datetime(*dt.timetuple()[:3]) \
|
||||
.replace(tzinfo=timezone_utc)
|
||||
return datetime.datetime(*dt.timetuple()[:3], tzinfo=datetime.timezone.utc)
|
||||
|
||||
def ceiling_to_hour(dt: datetime.datetime) -> datetime.datetime:
|
||||
floor = floor_to_hour(dt)
|
||||
|
@ -37,7 +34,7 @@ def ceiling_to_day(dt: datetime.datetime) -> datetime.datetime:
|
|||
return floor + datetime.timedelta(days=1)
|
||||
|
||||
def timestamp_to_datetime(timestamp: float) -> datetime.datetime:
|
||||
return datetime.datetime.fromtimestamp(float(timestamp), tz=timezone_utc)
|
||||
return datetime.datetime.fromtimestamp(float(timestamp), tz=datetime.timezone.utc)
|
||||
|
||||
def datetime_to_timestamp(dt: datetime.datetime) -> int:
|
||||
verify_UTC(dt)
|
||||
|
|
|
@ -3,7 +3,6 @@ import time
|
|||
from typing import Any
|
||||
|
||||
from django.core.management.base import CommandParser
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
from zerver.lib.management import ZulipBaseCommand
|
||||
from zerver.models import Message, Recipient, Stream
|
||||
|
@ -26,7 +25,7 @@ class Command(ZulipBaseCommand):
|
|||
streams = Stream.objects.filter(realm=realm, invite_only=False)
|
||||
recipients = Recipient.objects.filter(
|
||||
type=Recipient.STREAM, type_id__in=[stream.id for stream in streams])
|
||||
cutoff = datetime.datetime.fromtimestamp(options["since"], tz=timezone_utc)
|
||||
cutoff = datetime.datetime.fromtimestamp(options["since"], tz=datetime.timezone.utc)
|
||||
messages = Message.objects.filter(date_sent__gt=cutoff, recipient__in=recipients)
|
||||
|
||||
for message in messages:
|
||||
|
|
|
@ -17,7 +17,6 @@ from django.http import HttpResponse
|
|||
from django.db import transaction
|
||||
from django.db.models import F
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
from analytics.lib.counts import CountStat, LoggingCountStat
|
||||
from analytics.models import InstallationCount, RealmCount
|
||||
|
@ -383,7 +382,7 @@ class PushBouncerNotificationTest(BouncerTestCase):
|
|||
self.assertEqual(len(tokens), 0)
|
||||
|
||||
class AnalyticsBouncerTest(BouncerTestCase):
|
||||
TIME_ZERO = datetime.datetime(1988, 3, 14).replace(tzinfo=timezone_utc)
|
||||
TIME_ZERO = datetime.datetime(1988, 3, 14, tzinfo=datetime.timezone.utc)
|
||||
|
||||
@override_settings(PUSH_NOTIFICATION_BOUNCER_URL='https://push.zulip.org.example.com')
|
||||
@mock.patch('zerver.lib.remote_server.requests.request')
|
||||
|
|
|
@ -81,7 +81,6 @@ import ujson
|
|||
from typing import Any, List, Optional
|
||||
|
||||
import urllib
|
||||
import pytz
|
||||
|
||||
class RedirectAndLogIntoSubdomainTestCase(ZulipTestCase):
|
||||
def test_data(self) -> None:
|
||||
|
@ -4087,22 +4086,22 @@ class FollowupEmailTest(ZulipTestCase):
|
|||
def test_followup_day2_email(self) -> None:
|
||||
user_profile = self.example_user('hamlet')
|
||||
# Test date_joined == Sunday
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 7, 1, 0, 0, 0, pytz.UTC)
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 7, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
|
||||
self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=2, hours=-1))
|
||||
# Test date_joined == Tuesday
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 2, 1, 0, 0, 0, pytz.UTC)
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 2, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
|
||||
self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=2, hours=-1))
|
||||
# Test date_joined == Thursday
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 4, 1, 0, 0, 0, pytz.UTC)
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 4, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
|
||||
self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=1, hours=-1))
|
||||
# Test date_joined == Friday
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 5, 1, 0, 0, 0, pytz.UTC)
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 5, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
|
||||
self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=3, hours=-1))
|
||||
|
||||
# Time offset of America/Phoenix is -07:00
|
||||
user_profile.timezone = 'America/Phoenix'
|
||||
# Test date_joined == Friday in UTC, but Thursday in the user's timezone
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 5, 1, 0, 0, 0, pytz.UTC)
|
||||
user_profile.date_joined = datetime.datetime(2018, 1, 5, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
|
||||
self.assertEqual(followup_day2_email_delay(user_profile), datetime.timedelta(days=1, hours=-1))
|
||||
|
||||
class NoReplyEmailTest(ZulipTestCase):
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
from django.utils.timezone import utc as timezone_utc
|
||||
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.timestamp import floor_to_hour, floor_to_day, ceiling_to_hour, \
|
||||
timestamp_to_datetime, datetime_to_timestamp, \
|
||||
TimezoneNotUTCException, convert_to_UTC
|
||||
|
||||
from datetime import timedelta
|
||||
from datetime import timedelta, timezone
|
||||
from dateutil import parser
|
||||
import pytz
|
||||
|
||||
class TestTimestamp(ZulipTestCase):
|
||||
def test_datetime_and_timestamp_conversions(self) -> 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)]:
|
||||
parser.parse('2017-01-01 00:00:00.123').replace(tzinfo=timezone.utc)]:
|
||||
self.assertEqual(timestamp_to_datetime(timestamp), dt-timedelta(microseconds=123000))
|
||||
self.assertEqual(datetime_to_timestamp(dt), timestamp)
|
||||
|
||||
|
@ -28,7 +24,7 @@ class TestTimestamp(ZulipTestCase):
|
|||
def test_convert_to_UTC(self) -> None:
|
||||
utc_datetime = parser.parse('2017-01-01 00:00:00.123 UTC')
|
||||
for dt in [
|
||||
parser.parse('2017-01-01 00:00:00.123').replace(tzinfo=timezone_utc),
|
||||
parser.parse('2017-01-01 00:00:00.123').replace(tzinfo=timezone.utc),
|
||||
parser.parse('2017-01-01 00:00:00.123'),
|
||||
parser.parse('2017-01-01 05:00:00.123+05')]:
|
||||
self.assertEqual(convert_to_UTC(dt), utc_datetime)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Callable, Dict, List, Tuple
|
||||
|
||||
import ujson
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from zerver.decorator import api_key_only_webhook_view
|
||||
|
@ -41,7 +40,7 @@ class LibratoWebhookParser:
|
|||
def parse_violation(self, violation: Dict[str, Any]) -> Tuple[str, str]:
|
||||
metric_name = violation['metric']
|
||||
recorded_at = datetime.fromtimestamp((violation['recorded_at']),
|
||||
tz=timezone_utc).strftime('%Y-%m-%d %H:%M:%S')
|
||||
tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
|
||||
return metric_name, recorded_at
|
||||
|
||||
def parse_conditions(self) -> List[Dict[str, Any]]:
|
||||
|
@ -90,7 +89,7 @@ class LibratoWebhookHandler(LibratoWebhookParser):
|
|||
def handle_alert_clear_message(self) -> str:
|
||||
alert_clear_template = "Alert [alert_name]({alert_url}) has cleared at {trigger_time} UTC!"
|
||||
trigger_time = datetime.fromtimestamp((self.payload['trigger_time']),
|
||||
tz=timezone_utc).strftime('%Y-%m-%d %H:%M:%S')
|
||||
tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
|
||||
alert_id, alert_name, alert_url, alert_runbook_url = self.parse_alert()
|
||||
content = alert_clear_template.format(alert_name=alert_name,
|
||||
alert_url=alert_url,
|
||||
|
|
|
@ -7,7 +7,6 @@ from django.core.validators import validate_email, URLValidator
|
|||
from django.db import IntegrityError, transaction
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils import timezone
|
||||
from django.utils.timezone import utc as timezone_utc
|
||||
from django.utils.translation import ugettext as _, ugettext as err_
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
|
@ -224,7 +223,7 @@ def remote_server_post_analytics(request: HttpRequest,
|
|||
realm_id=row['realm'],
|
||||
remote_id=row['id'],
|
||||
server=server,
|
||||
end_time=datetime.datetime.fromtimestamp(row['end_time'], tz=timezone_utc),
|
||||
end_time=datetime.datetime.fromtimestamp(row['end_time'], tz=datetime.timezone.utc),
|
||||
subgroup=row['subgroup'],
|
||||
value=row['value']) for row in realm_counts]
|
||||
batch_create_table_data(server, RemoteRealmCount, row_objects)
|
||||
|
@ -233,7 +232,7 @@ def remote_server_post_analytics(request: HttpRequest,
|
|||
property=row['property'],
|
||||
remote_id=row['id'],
|
||||
server=server,
|
||||
end_time=datetime.datetime.fromtimestamp(row['end_time'], tz=timezone_utc),
|
||||
end_time=datetime.datetime.fromtimestamp(row['end_time'], tz=datetime.timezone.utc),
|
||||
subgroup=row['subgroup'],
|
||||
value=row['value']) for row in installation_counts]
|
||||
batch_create_table_data(server, RemoteInstallationCount, row_objects)
|
||||
|
@ -243,7 +242,7 @@ def remote_server_post_analytics(request: HttpRequest,
|
|||
realm_id=row['realm'],
|
||||
remote_id=row['id'],
|
||||
server=server,
|
||||
event_time=datetime.datetime.fromtimestamp(row['event_time'], tz=timezone_utc),
|
||||
event_time=datetime.datetime.fromtimestamp(row['event_time'], tz=datetime.timezone.utc),
|
||||
backfilled=row['backfilled'],
|
||||
extra_data=row['extra_data'],
|
||||
event_type=row['event_type']) for row in realmauditlog_rows]
|
||||
|
|
Loading…
Reference in New Issue