mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-09 17:45:32 -04:00
initial timezone pass, which breaks many tests
This commit is contained in:
2
Pipfile
2
Pipfile
@@ -20,7 +20,7 @@ humanize = "==4.1.0"
|
|||||||
itsdangerous = "==2.1.2"
|
itsdangerous = "==2.1.2"
|
||||||
jinja2 = "==3.1.2"
|
jinja2 = "==3.1.2"
|
||||||
notifications-python-client = "==6.3.0"
|
notifications-python-client = "==6.3.0"
|
||||||
notifications-utils = {version = "==56.0.3", git = "https://github.com/GSA/notifications-utils.git"}
|
notifications-utils = {editable = true, ref = "987646ec18d32dfe8b4ea55b83d68e31e2f85104", git = "https://github.com/GSA/notifications-utils"}
|
||||||
prometheus-client = "==0.14.1"
|
prometheus-client = "==0.14.1"
|
||||||
pyexcel = "==0.7.0"
|
pyexcel = "==0.7.0"
|
||||||
pyexcel-io = "==0.6.6"
|
pyexcel-io = "==0.6.6"
|
||||||
|
|||||||
95
Pipfile.lock
generated
95
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "5518009c6350eb8a3b7d17d37e5b5b3c02920f2a1685b0adbc30b132ac81748d"
|
"sha256": "fec017c4f1741245ca6d3efc3c1fd115425d392d45745831728c52b8d2b1f5f3"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
@@ -34,11 +34,11 @@
|
|||||||
},
|
},
|
||||||
"awscli": {
|
"awscli": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:1a794b2c12cf370db7601b2b2bb1bec9aafda0666943895f401bb71fdbdd29f9",
|
"sha256:74bf6f184df0faf4fedbfea3ea8665b4ace327d03c48d21be81c66f4979a3cc0",
|
||||||
"sha256:e43ecfaa173d7af6d557f746b41827b831908b3c5db3572b352df0c0ab514dc3"
|
"sha256:92c1f8c53dba20ba12f64345f2d162d994a3a842eeabfb5e826d8f296e9348d5"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==1.27.4"
|
"version": "==1.27.14"
|
||||||
},
|
},
|
||||||
"awscli-cwlogs": {
|
"awscli-cwlogs": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -64,19 +64,19 @@
|
|||||||
},
|
},
|
||||||
"boto3": {
|
"boto3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:244fd0776fc1f69c3ed34f359db7a90a6108372486abc999ce8515a79bbfc86e",
|
"sha256:9841e0bec9697979394632e33588e57c7bbf60e3c384740df0acadfe5014d709",
|
||||||
"sha256:9bfe15f394a7cd8ca2520e42722269d9aa2bbc222e348283c527d3aa88484314"
|
"sha256:d61c97ed51a16f66b6ce5321e611626b0120e80cc41025c6f58e281859d7fbf8"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==1.26.4"
|
"version": "==1.26.14"
|
||||||
},
|
},
|
||||||
"botocore": {
|
"botocore": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:4c7dedc1096417ac8a120a3f42b81bddaec5451cdd6add7af98680903fd73b18",
|
"sha256:208ca5c3d8299d45a19b912dc791e3297d2961873ff37131d4fc3eb86365645c",
|
||||||
"sha256:fa86747f5092723c0dc7f201a48cdfac3ad8d03dd6cb7abc189abc708be43269"
|
"sha256:20fb0978beac90fd8c45b57936f2c1c182e19f1622b09a481a050723632a485c"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==1.29.4"
|
"version": "==1.29.14"
|
||||||
},
|
},
|
||||||
"cachetools": {
|
"cachetools": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -267,10 +267,10 @@
|
|||||||
},
|
},
|
||||||
"eventlet": {
|
"eventlet": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:a085922698e5029f820cf311a648ac324d73cec0e4792877609d978a4b5bbf31",
|
"sha256:82c382c2a2c712f1a8320378a9120ac9589d9f1131c36a63780f0b8504afa5bc",
|
||||||
"sha256:afbe17f06a58491e9aebd7a4a03e70b0b63fd4cf76d8307bae07f280479b1515"
|
"sha256:96039b9389dbb4431b1c0a6e42ea1326628cc7ad63a6280b02947f111d3d8e04"
|
||||||
],
|
],
|
||||||
"version": "==0.33.1"
|
"version": "==0.33.2"
|
||||||
},
|
},
|
||||||
"fido2": {
|
"fido2": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -346,6 +346,7 @@
|
|||||||
"greenlet": {
|
"greenlet": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9",
|
"sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9",
|
||||||
|
"sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9",
|
||||||
"sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581",
|
"sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581",
|
||||||
"sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26",
|
"sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26",
|
||||||
"sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd",
|
"sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd",
|
||||||
@@ -370,6 +371,7 @@
|
|||||||
"sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94",
|
"sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94",
|
||||||
"sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92",
|
"sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92",
|
||||||
"sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e",
|
"sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e",
|
||||||
|
"sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726",
|
||||||
"sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd",
|
"sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd",
|
||||||
"sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5",
|
"sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5",
|
||||||
"sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764",
|
"sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764",
|
||||||
@@ -395,6 +397,7 @@
|
|||||||
"sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7",
|
"sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7",
|
||||||
"sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d",
|
"sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d",
|
||||||
"sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d",
|
"sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d",
|
||||||
|
"sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0",
|
||||||
"sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243",
|
"sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243",
|
||||||
"sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce",
|
"sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce",
|
||||||
"sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6",
|
"sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6",
|
||||||
@@ -606,9 +609,9 @@
|
|||||||
"version": "==6.3.0"
|
"version": "==6.3.0"
|
||||||
},
|
},
|
||||||
"notifications-utils": {
|
"notifications-utils": {
|
||||||
"git": "https://github.com/GSA/notifications-utils.git",
|
"editable": true,
|
||||||
"ref": "224313e76caa56d60577c63006a6220ee63fb96b",
|
"git": "https://github.com/GSA/notifications-utils",
|
||||||
"version": "==56.0.3"
|
"ref": "987646ec18d32dfe8b4ea55b83d68e31e2f85104"
|
||||||
},
|
},
|
||||||
"openpyxl": {
|
"openpyxl": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -737,11 +740,11 @@
|
|||||||
},
|
},
|
||||||
"pypdf2": {
|
"pypdf2": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:3c7badd512c21711eb1789c2eadbf96279289c0f94452ee54a86473bfbefd732",
|
"sha256:7074034d199a817f3c0190c533a1a64ed4237cc060cdb1ebc3a6da796a2c71c0",
|
||||||
"sha256:7291a552ead2e7c2d556cce03bf71842fbbab478fcba13ae75ab1d59746b4dcb"
|
"sha256:f1b0df8cd686d2ed069088b903ec65fb0f53e9c7837adc8139eccfbb7eb9141f"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.6'",
|
"markers": "python_version >= '3.6'",
|
||||||
"version": "==2.11.1"
|
"version": "==2.11.2"
|
||||||
},
|
},
|
||||||
"pyproj": {
|
"pyproj": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -883,11 +886,11 @@
|
|||||||
},
|
},
|
||||||
"setuptools": {
|
"setuptools": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
|
"sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840",
|
||||||
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
|
"sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==65.5.1"
|
"version": "==65.6.0"
|
||||||
},
|
},
|
||||||
"shapely": {
|
"shapely": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -957,10 +960,10 @@
|
|||||||
},
|
},
|
||||||
"texttable": {
|
"texttable": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:42ee7b9e15f7b225747c3fa08f43c5d6c83bc899f80ff9bae9319334824076e9",
|
"sha256:a169c9a3598f2ef3721123c2951fdaa954dae4593a4adef0a855eb02955f83ff",
|
||||||
"sha256:dd2b0eaebb2a9e167d1cefedab4700e5dcbdb076114eed30b58b97ed6b37d6f2"
|
"sha256:fc3f763a89796ae03789a02343bd4e8fed9735935123b1bfb9537a5935852315"
|
||||||
],
|
],
|
||||||
"version": "==1.6.4"
|
"version": "==1.6.5"
|
||||||
},
|
},
|
||||||
"typing-extensions": {
|
"typing-extensions": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -1122,19 +1125,19 @@
|
|||||||
},
|
},
|
||||||
"boto3": {
|
"boto3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:244fd0776fc1f69c3ed34f359db7a90a6108372486abc999ce8515a79bbfc86e",
|
"sha256:9841e0bec9697979394632e33588e57c7bbf60e3c384740df0acadfe5014d709",
|
||||||
"sha256:9bfe15f394a7cd8ca2520e42722269d9aa2bbc222e348283c527d3aa88484314"
|
"sha256:d61c97ed51a16f66b6ce5321e611626b0120e80cc41025c6f58e281859d7fbf8"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==1.26.4"
|
"version": "==1.26.14"
|
||||||
},
|
},
|
||||||
"botocore": {
|
"botocore": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:4c7dedc1096417ac8a120a3f42b81bddaec5451cdd6add7af98680903fd73b18",
|
"sha256:208ca5c3d8299d45a19b912dc791e3297d2961873ff37131d4fc3eb86365645c",
|
||||||
"sha256:fa86747f5092723c0dc7f201a48cdfac3ad8d03dd6cb7abc189abc708be43269"
|
"sha256:20fb0978beac90fd8c45b57936f2c1c182e19f1622b09a481a050723632a485c"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==1.29.4"
|
"version": "==1.29.14"
|
||||||
},
|
},
|
||||||
"cachecontrol": {
|
"cachecontrol": {
|
||||||
"extras": [
|
"extras": [
|
||||||
@@ -1560,11 +1563,11 @@
|
|||||||
},
|
},
|
||||||
"pip-audit": {
|
"pip-audit": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:6c7fd7c300559c99963f0b4be4543c55175e1550534228b8d27bce7dcd06ab34",
|
"sha256:00ebef2a52884627f255b879135e28001de4378b8005318b66cc3a802459ee0a",
|
||||||
"sha256:be866655a365714c98782e00e64b092383ffb9171680aaaa0fb50ba75d775022"
|
"sha256:d6d830bdbe3fd3efaf54f4a203451f286e75aecb7e44f9f84f7bfbd38aba26ac"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.4.5"
|
"version": "==2.4.6"
|
||||||
},
|
},
|
||||||
"pip-requirements-parser": {
|
"pip-requirements-parser": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -1737,10 +1740,10 @@
|
|||||||
},
|
},
|
||||||
"resolvelib": {
|
"resolvelib": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:c6ea56732e9fb6fca1b2acc2ccc68a0b6b8c566d8f3e78e0443310ede61dbd37",
|
"sha256:40ab05117c3281b1b160105e10075094c5ab118315003c922b77673a365290e1",
|
||||||
"sha256:d9b7907f055c3b3a2cfc56c914ffd940122915826ff5fb5b1de0c99778f4de98"
|
"sha256:597adcbdf81d62d0cde55d90faa8e79187ec0f18e5012df30bd7a751b26343ae"
|
||||||
],
|
],
|
||||||
"version": "==0.8.1"
|
"version": "==0.9.0"
|
||||||
},
|
},
|
||||||
"responses": {
|
"responses": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -1768,11 +1771,11 @@
|
|||||||
},
|
},
|
||||||
"setuptools": {
|
"setuptools": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
|
"sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840",
|
||||||
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
|
"sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.7'",
|
"markers": "python_version >= '3.7'",
|
||||||
"version": "==65.5.1"
|
"version": "==65.6.0"
|
||||||
},
|
},
|
||||||
"six": {
|
"six": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -1807,11 +1810,11 @@
|
|||||||
},
|
},
|
||||||
"stevedore": {
|
"stevedore": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:02518a8f0d6d29be8a445b7f2ac63753ff29e8f2a2faa01777568d5500d777a6",
|
"sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a",
|
||||||
"sha256:3b1cbd592a87315f000d05164941ee5e164899f8fc0ce9a00bb0f321f40ef93e"
|
"sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.8'",
|
"markers": "python_version >= '3.8'",
|
||||||
"version": "==4.1.0"
|
"version": "==4.1.1"
|
||||||
},
|
},
|
||||||
"toml": {
|
"toml": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@@ -1831,10 +1834,10 @@
|
|||||||
},
|
},
|
||||||
"types-toml": {
|
"types-toml": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:8300fd093e5829eb9c1fba69cee38130347d4b74ddf32d0a7df650ae55c2b599",
|
"sha256:171bdb3163d79a520560f24ba916a9fc9bff81659c5448a9fea89240923722be",
|
||||||
"sha256:b7e7ea572308b1030dc86c3ba825c5210814c2825612ec679eb7814f8dd9295a"
|
"sha256:b7b5c4977f96ab7b5ac06d8a6590d17c0bf252a96efc03b109c2711fb3e0eafd"
|
||||||
],
|
],
|
||||||
"version": "==0.10.8"
|
"version": "==0.10.8.1"
|
||||||
},
|
},
|
||||||
"urllib3": {
|
"urllib3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class Config(object):
|
|||||||
HEADER_COLOUR = '#81878b' # mix(govuk-colour("dark-grey"), govuk-colour("mid-grey"))
|
HEADER_COLOUR = '#81878b' # mix(govuk-colour("dark-grey"), govuk-colour("mid-grey"))
|
||||||
LOGO_CDN_DOMAIN = 'static-logos.notifications.service.gov.uk' # TODO use our own CDN
|
LOGO_CDN_DOMAIN = 'static-logos.notifications.service.gov.uk' # TODO use our own CDN
|
||||||
ASSETS_DEBUG = False
|
ASSETS_DEBUG = False
|
||||||
|
TIMEZONE = os.environ.get('TIMEZONE', 'America/New_York')
|
||||||
|
|
||||||
# Credentials
|
# Credentials
|
||||||
ADMIN_CLIENT_SECRET = os.environ.get('ADMIN_CLIENT_SECRET')
|
ADMIN_CLIENT_SECRET = os.environ.get('ADMIN_CLIENT_SECRET')
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from numbers import Number
|
|||||||
import ago
|
import ago
|
||||||
import dateutil
|
import dateutil
|
||||||
import humanize
|
import humanize
|
||||||
|
import pytz
|
||||||
from flask import Markup, url_for
|
from flask import Markup, url_for
|
||||||
from notifications_utils.field import Field
|
from notifications_utils.field import Field
|
||||||
from notifications_utils.formatters import make_quotes_smart
|
from notifications_utils.formatters import make_quotes_smart
|
||||||
@@ -18,7 +19,7 @@ from notifications_utils.recipients import (
|
|||||||
validate_phone_number,
|
validate_phone_number,
|
||||||
)
|
)
|
||||||
from notifications_utils.take import Take
|
from notifications_utils.take import Take
|
||||||
from notifications_utils.timezones import utc_string_to_aware_gmt_datetime
|
from notifications_utils.timezones import convert_utc_to_local_timezone
|
||||||
|
|
||||||
|
|
||||||
def convert_to_boolean(value):
|
def convert_to_boolean(value):
|
||||||
@@ -74,17 +75,18 @@ def format_datetime_numeric(date):
|
|||||||
|
|
||||||
|
|
||||||
def format_date_numeric(date):
|
def format_date_numeric(date):
|
||||||
return utc_string_to_aware_gmt_datetime(date).strftime('%Y-%m-%d')
|
return convert_utc_to_local_timezone(date).strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
|
||||||
def format_time_24h(date):
|
def format_time_24h(date):
|
||||||
return utc_string_to_aware_gmt_datetime(date).strftime('%H:%M')
|
return convert_utc_to_local_timezone(date).strftime('%H:%M')
|
||||||
|
|
||||||
|
|
||||||
def get_human_day(time, date_prefix=''):
|
def get_human_day(time, date_prefix=''):
|
||||||
|
|
||||||
# Add 1 minute to transform 00:00 into ‘midnight today’ instead of ‘midnight tomorrow’
|
# Add 1 minute to transform 00:00 into ‘midnight today’ instead of ‘midnight tomorrow’
|
||||||
date = (utc_string_to_aware_gmt_datetime(time) - timedelta(minutes=1)).date()
|
time = dateutil.parser.parse(time, ignoretz=True)
|
||||||
|
date = (convert_utc_to_local_timezone(time) - timedelta(minutes=1)).date()
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
|
|
||||||
if date == (now + timedelta(days=1)).date():
|
if date == (now + timedelta(days=1)).date():
|
||||||
@@ -106,25 +108,26 @@ def get_human_day(time, date_prefix=''):
|
|||||||
|
|
||||||
|
|
||||||
def format_time(date):
|
def format_time(date):
|
||||||
|
date = dateutil.parser.parse(date, ignoretz=True)
|
||||||
return {
|
return {
|
||||||
'12:00AM': 'Midnight',
|
'12:00AM': 'Midnight',
|
||||||
'12:00PM': 'Midday'
|
'12:00PM': 'Noon'
|
||||||
}.get(
|
}.get(
|
||||||
utc_string_to_aware_gmt_datetime(date).strftime('%-I:%M%p'),
|
convert_utc_to_local_timezone(date).strftime('%-I:%M%p'),
|
||||||
utc_string_to_aware_gmt_datetime(date).strftime('%-I:%M%p')
|
convert_utc_to_local_timezone(date).strftime('%-I:%M%p')
|
||||||
).lower()
|
).lower()
|
||||||
|
|
||||||
|
|
||||||
def format_date(date):
|
def format_date(date):
|
||||||
return utc_string_to_aware_gmt_datetime(date).strftime('%A %d %B %Y')
|
return convert_utc_to_local_timezone(date).strftime('%A %d %B %Y')
|
||||||
|
|
||||||
|
|
||||||
def format_date_normal(date):
|
def format_date_normal(date):
|
||||||
return utc_string_to_aware_gmt_datetime(date).strftime('%d %B %Y').lstrip('0')
|
return convert_utc_to_local_timezone(date).strftime('%d %B %Y').lstrip('0')
|
||||||
|
|
||||||
|
|
||||||
def format_date_short(date):
|
def format_date_short(date):
|
||||||
return _format_datetime_short(utc_string_to_aware_gmt_datetime(date))
|
return _format_datetime_short(convert_utc_to_local_timezone(date))
|
||||||
|
|
||||||
|
|
||||||
def format_date_human(date):
|
def format_date_human(date):
|
||||||
@@ -139,7 +142,7 @@ def format_datetime_human(date, date_prefix=''):
|
|||||||
|
|
||||||
|
|
||||||
def format_day_of_week(date):
|
def format_day_of_week(date):
|
||||||
return utc_string_to_aware_gmt_datetime(date).strftime('%A')
|
return convert_utc_to_local_timezone(date).strftime('%A')
|
||||||
|
|
||||||
|
|
||||||
def _format_datetime_short(datetime):
|
def _format_datetime_short(datetime):
|
||||||
@@ -155,10 +158,11 @@ def naturaltime_without_indefinite_article(date):
|
|||||||
|
|
||||||
|
|
||||||
def format_delta(date):
|
def format_delta(date):
|
||||||
|
date = dateutil.parser.parse(date, ignoretz=True)
|
||||||
delta = (
|
delta = (
|
||||||
datetime.now(timezone.utc)
|
datetime.now(timezone.utc)
|
||||||
) - (
|
) - (
|
||||||
utc_string_to_aware_gmt_datetime(date)
|
convert_utc_to_local_timezone(date).replace(tzinfo=pytz.utc)
|
||||||
)
|
)
|
||||||
if delta < timedelta(seconds=30):
|
if delta < timedelta(seconds=30):
|
||||||
return "just now"
|
return "just now"
|
||||||
@@ -168,8 +172,9 @@ def format_delta(date):
|
|||||||
|
|
||||||
|
|
||||||
def format_delta_days(date):
|
def format_delta_days(date):
|
||||||
|
date = dateutil.parser.parse(date, ignoretz=True)
|
||||||
now = datetime.now(timezone.utc)
|
now = datetime.now(timezone.utc)
|
||||||
date = utc_string_to_aware_gmt_datetime(date)
|
date = convert_utc_to_local_timezone(date).replace(tzinfo=pytz.utc)
|
||||||
if date.strftime('%Y-%m-%d') == now.strftime('%Y-%m-%d'):
|
if date.strftime('%Y-%m-%d') == now.strftime('%Y-%m-%d'):
|
||||||
return "today"
|
return "today"
|
||||||
if date.strftime('%Y-%m-%d') == (now - timedelta(days=1)).strftime('%Y-%m-%d'):
|
if date.strftime('%Y-%m-%d') == (now - timedelta(days=1)).strftime('%Y-%m-%d'):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from itertools import chain
|
|||||||
from numbers import Number
|
from numbers import Number
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from flask import Markup, render_template, request
|
from flask import Markup, current_app, render_template, request
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from flask_wtf import FlaskForm as Form
|
from flask_wtf import FlaskForm as Form
|
||||||
from flask_wtf.file import FileAllowed
|
from flask_wtf.file import FileAllowed
|
||||||
@@ -77,8 +77,8 @@ def get_time_value_and_label(future_time):
|
|||||||
return (
|
return (
|
||||||
future_time.replace(tzinfo=None).isoformat(),
|
future_time.replace(tzinfo=None).isoformat(),
|
||||||
'{} at {}'.format(
|
'{} at {}'.format(
|
||||||
get_human_day(future_time.astimezone(pytz.timezone('Europe/London'))),
|
get_human_day(future_time.astimezone(pytz.timezone(current_app.config['TIMEZONE']))),
|
||||||
get_human_time(future_time.astimezone(pytz.timezone('Europe/London')))
|
get_human_time(future_time.astimezone(pytz.timezone(current_app.config['TIMEZONE'])))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from notifications_python_client.errors import HTTPError
|
|||||||
from notifications_utils.clients.zendesk.zendesk_client import (
|
from notifications_utils.clients.zendesk.zendesk_client import (
|
||||||
NotifySupportTicket,
|
NotifySupportTicket,
|
||||||
)
|
)
|
||||||
from notifications_utils.timezones import utc_string_to_aware_gmt_datetime
|
from notifications_utils.timezones import convert_utc_to_local_timezone
|
||||||
|
|
||||||
from app import (
|
from app import (
|
||||||
billing_api_client,
|
billing_api_client,
|
||||||
@@ -440,8 +440,8 @@ def get_service_verify_reply_to_address_partials(service_id, notification_id):
|
|||||||
is_default=is_default
|
is_default=is_default
|
||||||
)
|
)
|
||||||
seconds_since_sending = (
|
seconds_since_sending = (
|
||||||
utc_string_to_aware_gmt_datetime(datetime.utcnow().isoformat()) -
|
convert_utc_to_local_timezone(datetime.utcnow().isoformat()) -
|
||||||
utc_string_to_aware_gmt_datetime(notification['created_at'])
|
convert_utc_to_local_timezone(notification['created_at'])
|
||||||
).seconds
|
).seconds
|
||||||
if notification["status"] in FAILURE_STATUSES or (
|
if notification["status"] in FAILURE_STATUSES or (
|
||||||
notification["status"] in SENDING_STATUSES and
|
notification["status"] in SENDING_STATUSES and
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from notifications_utils.letter_timings import (
|
|||||||
get_letter_timings,
|
get_letter_timings,
|
||||||
letter_can_be_cancelled,
|
letter_can_be_cancelled,
|
||||||
)
|
)
|
||||||
from notifications_utils.timezones import utc_string_to_aware_gmt_datetime
|
from notifications_utils.timezones import convert_utc_to_local_timezone
|
||||||
from werkzeug.utils import cached_property
|
from werkzeug.utils import cached_property
|
||||||
|
|
||||||
from app.models import JSONModel, ModelList, PaginatedModelList
|
from app.models import JSONModel, ModelList, PaginatedModelList
|
||||||
@@ -150,7 +150,7 @@ class Job(JSONModel):
|
|||||||
|
|
||||||
if not letter_can_be_cancelled(
|
if not letter_can_be_cancelled(
|
||||||
'created',
|
'created',
|
||||||
utc_string_to_aware_gmt_datetime(self.created_at).replace(tzinfo=None)
|
convert_utc_to_local_timezone(self.created_at).replace(tzinfo=None)
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ class Job(JSONModel):
|
|||||||
# We have to make the time just before 5:30pm because a
|
# We have to make the time just before 5:30pm because a
|
||||||
# letter uploaded at 5:30pm will be printed the next day
|
# letter uploaded at 5:30pm will be printed the next day
|
||||||
(
|
(
|
||||||
utc_string_to_aware_gmt_datetime(self.created_at) - timedelta(minutes=1)
|
convert_utc_to_local_timezone(self.created_at) - timedelta(minutes=1)
|
||||||
).astimezone(pytz.utc).isoformat(),
|
).astimezone(pytz.utc).isoformat(),
|
||||||
long_form=False,
|
long_form=False,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from datetime import datetime
|
|||||||
from flask import abort, request, session
|
from flask import abort, request, session
|
||||||
from flask_login import AnonymousUserMixin, UserMixin, login_user, logout_user
|
from flask_login import AnonymousUserMixin, UserMixin, login_user, logout_user
|
||||||
from notifications_python_client.errors import HTTPError
|
from notifications_python_client.errors import HTTPError
|
||||||
from notifications_utils.timezones import utc_string_to_aware_gmt_datetime
|
from notifications_utils.timezones import convert_utc_to_local_timezone
|
||||||
from werkzeug.utils import cached_property
|
from werkzeug.utils import cached_property
|
||||||
|
|
||||||
from app.event_handlers import (
|
from app.event_handlers import (
|
||||||
@@ -126,9 +126,9 @@ class User(JSONModel, UserMixin):
|
|||||||
def password_changed_more_recently_than(self, datetime_string):
|
def password_changed_more_recently_than(self, datetime_string):
|
||||||
if not self.password_changed_at:
|
if not self.password_changed_at:
|
||||||
return False
|
return False
|
||||||
return utc_string_to_aware_gmt_datetime(
|
return convert_utc_to_local_timezone(
|
||||||
self.password_changed_at
|
self.password_changed_at
|
||||||
) > utc_string_to_aware_gmt_datetime(
|
) > convert_utc_to_local_timezone(
|
||||||
datetime_string
|
datetime_string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -7,17 +7,16 @@ from notifications_utils.formatters import unescaped_formatted_list
|
|||||||
from notifications_utils.letter_timings import letter_can_be_cancelled
|
from notifications_utils.letter_timings import letter_can_be_cancelled
|
||||||
from notifications_utils.postal_address import PostalAddress
|
from notifications_utils.postal_address import PostalAddress
|
||||||
from notifications_utils.timezones import (
|
from notifications_utils.timezones import (
|
||||||
convert_bst_to_utc,
|
convert_local_timezone_to_utc,
|
||||||
convert_utc_to_bst,
|
convert_utc_to_local_timezone,
|
||||||
utc_string_to_aware_gmt_datetime,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def printing_today_or_tomorrow(created_at):
|
def printing_today_or_tomorrow(created_at):
|
||||||
print_cutoff = convert_bst_to_utc(
|
print_cutoff = convert_local_timezone_to_utc(
|
||||||
convert_utc_to_bst(datetime.utcnow()).replace(hour=17, minute=30)
|
convert_utc_to_local_timezone(datetime.utcnow()).replace(hour=17, minute=30)
|
||||||
).replace(tzinfo=pytz.utc)
|
).replace(tzinfo=pytz.utc)
|
||||||
created_at = utc_string_to_aware_gmt_datetime(created_at)
|
created_at = convert_utc_to_local_timezone(created_at)
|
||||||
|
|
||||||
if created_at < print_cutoff:
|
if created_at < print_cutoff:
|
||||||
return 'today'
|
return 'today'
|
||||||
@@ -31,7 +30,7 @@ def get_letter_printing_statement(status, created_at, long_form=True):
|
|||||||
decription = 'Printing starts' if long_form else 'Printing'
|
decription = 'Printing starts' if long_form else 'Printing'
|
||||||
return f'{decription} {printing_today_or_tomorrow(created_at)} at 5:30pm'
|
return f'{decription} {printing_today_or_tomorrow(created_at)} at 5:30pm'
|
||||||
else:
|
else:
|
||||||
printed_datetime = utc_string_to_aware_gmt_datetime(created_at) + timedelta(hours=6, minutes=30)
|
printed_datetime = convert_utc_to_local_timezone(created_at) + timedelta(hours=6, minutes=30)
|
||||||
if printed_datetime.date() == datetime.now().date():
|
if printed_datetime.date() == datetime.now().date():
|
||||||
return 'Printed today at 5:30pm'
|
return 'Printed today at 5:30pm'
|
||||||
elif printed_datetime.date() == datetime.now().date() - timedelta(days=1):
|
elif printed_datetime.date() == datetime.now().date() - timedelta(days=1):
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
from notifications_utils.timezones import utc_string_to_aware_gmt_datetime
|
from notifications_utils.timezones import convert_utc_to_local_timezone
|
||||||
|
|
||||||
|
|
||||||
def get_current_financial_year():
|
def get_current_financial_year():
|
||||||
now = utc_string_to_aware_gmt_datetime(
|
now = convert_utc_to_local_timezone(
|
||||||
datetime.utcnow()
|
datetime.utcnow()
|
||||||
)
|
)
|
||||||
current_month = int(now.strftime('%-m'))
|
current_month = int(now.strftime('%-m'))
|
||||||
|
|||||||
@@ -59,38 +59,40 @@ def test_format_number_in_pounds_as_currency(input_number, formatted_number):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('time, human_readable_datetime', [
|
@pytest.mark.parametrize('time, human_readable_datetime', [
|
||||||
('2018-03-14 09:00', '14 March at 9:00am'),
|
# incoming in UTC, outgoing in local timezone
|
||||||
('2018-03-14 15:00', '14 March at 3:00pm'),
|
# this test assumes timezone is America/New_York
|
||||||
|
('2018-03-14 09:00', '14 March at 5:00am'),
|
||||||
|
('2018-03-14 19:00', '14 March at 3:00pm'),
|
||||||
|
|
||||||
('2018-03-15 09:00', '15 March at 9:00am'),
|
('2018-03-15 09:00', '15 March at 5:00am'),
|
||||||
('2018-03-15 15:00', '15 March at 3:00pm'),
|
('2018-03-15 19:00', '15 March at 3:00pm'),
|
||||||
|
|
||||||
('2018-03-19 09:00', '19 March at 9:00am'),
|
('2018-03-19 09:00', '19 March at 5:00am'),
|
||||||
('2018-03-19 15:00', '19 March at 3:00pm'),
|
('2018-03-19 19:00', '19 March at 3:00pm'),
|
||||||
('2018-03-19 23:59', '19 March at 11:59pm'),
|
('2018-03-19 23:59', '19 March at 7:59pm'),
|
||||||
|
|
||||||
('2018-03-20 00:00', '19 March at midnight'), # we specifically refer to 00:00 as belonging to the day before.
|
('2018-03-20 04:00', '19 March at midnight'), # we specifically refer to 00:00 as belonging to the day before.
|
||||||
('2018-03-20 00:01', 'yesterday at 12:01am'),
|
('2018-03-20 04:01', 'yesterday at 12:01am'),
|
||||||
('2018-03-20 09:00', 'yesterday at 9:00am'),
|
('2018-03-20 09:00', 'yesterday at 5:00am'),
|
||||||
('2018-03-20 15:00', 'yesterday at 3:00pm'),
|
('2018-03-20 19:00', 'yesterday at 3:00pm'),
|
||||||
('2018-03-20 23:59', 'yesterday at 11:59pm'),
|
('2018-03-20 23:59', 'yesterday at 7:59pm'),
|
||||||
|
|
||||||
('2018-03-21 00:00', 'yesterday at midnight'), # we specifically refer to 00:00 as belonging to the day before.
|
('2018-03-21 04:00', 'yesterday at midnight'), # we specifically refer to 00:00 as belonging to the day before.
|
||||||
('2018-03-21 00:01', 'today at 12:01am'),
|
('2018-03-21 04:01', 'today at 12:01am'),
|
||||||
('2018-03-21 09:00', 'today at 9:00am'),
|
('2018-03-21 09:00', 'today at 5:00am'),
|
||||||
('2018-03-21 12:00', 'today at midday'),
|
('2018-03-21 16:00', 'today at noon'),
|
||||||
('2018-03-21 15:00', 'today at 3:00pm'),
|
('2018-03-21 19:00', 'today at 3:00pm'),
|
||||||
('2018-03-21 23:59', 'today at 11:59pm'),
|
('2018-03-21 23:59', 'today at 7:59pm'),
|
||||||
|
|
||||||
('2018-03-22 00:00', 'today at midnight'), # we specifically refer to 00:00 as belonging to the day before.
|
('2018-03-22 04:00', 'today at midnight'), # we specifically refer to 00:00 as belonging to the day before.
|
||||||
('2018-03-22 00:01', 'tomorrow at 12:01am'),
|
('2018-03-22 04:01', 'tomorrow at 12:01am'),
|
||||||
('2018-03-22 09:00', 'tomorrow at 9:00am'),
|
('2018-03-22 09:00', 'tomorrow at 5:00am'),
|
||||||
('2018-03-22 15:00', 'tomorrow at 3:00pm'),
|
('2018-03-22 19:00', 'tomorrow at 3:00pm'),
|
||||||
('2018-03-22 23:59', 'tomorrow at 11:59pm'),
|
('2018-03-22 23:59', 'tomorrow at 7:59pm'),
|
||||||
|
|
||||||
('2018-03-23 00:01', '23 March at 12:01am'),
|
('2018-03-23 04:01', '23 March at 12:01am'),
|
||||||
('2018-03-23 09:00', '23 March at 9:00am'),
|
('2018-03-23 09:00', '23 March at 5:00am'),
|
||||||
('2018-03-23 15:00', '23 March at 3:00pm'),
|
('2018-03-23 19:00', '23 March at 3:00pm'),
|
||||||
|
|
||||||
])
|
])
|
||||||
def test_format_datetime_relative(time, human_readable_datetime):
|
def test_format_datetime_relative(time, human_readable_datetime):
|
||||||
|
|||||||
Reference in New Issue
Block a user