From 9d049cea2e0c2dc65d0776b4af73d501f1ff27c8 Mon Sep 17 00:00:00 2001 From: zihan Date: Fri, 29 Nov 2019 18:56:41 -0500 Subject: [PATCH 01/14] New Token "x" Added for "X" token now we can show timestamp in float number for "x" token eliminated the zeros in the end --- arrow/formatter.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index ad1ac671e..e524c2a5f 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -10,9 +10,13 @@ class DateTimeFormatter(object): + + # This pattern matches characters enclosed in square brackes are matched as + # an atomic group. For more info on atomic groups and how to they are + # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X)" + r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x)" ) def __init__(self, locale="en_us"): @@ -25,6 +29,9 @@ def format(cls, dt, fmt): def _format_token(self, dt, token): + if token and token.startswith("[") and token.endswith("]"): + return token[1:-1] + if token == "YYYY": return self.locale.year_full(dt.year) if token == "YY": @@ -91,7 +98,13 @@ def _format_token(self, dt, token): return str(int(dt.microsecond / 100000)) if token == "X": - return str(calendar.timegm(dt.utctimetuple())) + microsecond = str(int(dt.microsecond)) + return str(calendar.timegm(dt.utctimetuple())) + '.' + microsecond + + if token == "x": + microsecond = str(int(dt.microsecond)) + + return str(calendar.timegm(dt.utctimetuple())) + microsecond.rstrip('0') if token == "ZZZ": return dt.tzname() From 98532f1b531b4ce187696fe707c65dc4f2318e40 Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 19:25:32 -0500 Subject: [PATCH 02/14] Update formatter_tests.py --- tests/formatter_tests.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index 0ed94f340..35bfbffca 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -104,11 +104,12 @@ def test_sub_second(self): self.assertEqual(self.formatter._format_token(dt, "S"), "0") def test_timestamp(self): - - timestamp = time.time() - dt = datetime.utcfromtimestamp(timestamp) - self.assertEqual(self.formatter._format_token(dt, "X"), str(int(timestamp))) - + dt = datetime(2019, 12, 3, 0, 20, 1, 728968) + self.assertEqual(self.formatter._format_token(dt, "X"), "1575332401.728968") + + dt = datetime(2019, 12, 3, 0, 20, 1, 728968) + self.assertEqual(self.formatter._format_token(dt, "X"), "1575332401728968") + def test_timezone(self): dt = datetime.utcnow().replace(tzinfo=dateutil_tz.gettz("US/Pacific")) From 46d05a79dc99e6d69e447c8dc2615cfbfae9adbf Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 19:29:11 -0500 Subject: [PATCH 03/14] Update formatter.py --- arrow/formatter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index e524c2a5f..7954ab872 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -16,7 +16,7 @@ class DateTimeFormatter(object): # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x)" + r"(YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x)" ) def __init__(self, locale="en_us"): From 4962a7524588d6cf4435cf7850c8801f51e2d8ef Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 19:40:51 -0500 Subject: [PATCH 04/14] Update formatter.py --- arrow/formatter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index 7954ab872..843480004 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -16,7 +16,7 @@ class DateTimeFormatter(object): # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x)" + r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X)" ) def __init__(self, locale="en_us"): From 22e6af533c4aedcb9bced2f77fbcceebe187c749 Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 19:52:24 -0500 Subject: [PATCH 05/14] Update formatter_tests.py --- tests/formatter_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index 35bfbffca..712d57eb0 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -108,7 +108,7 @@ def test_timestamp(self): self.assertEqual(self.formatter._format_token(dt, "X"), "1575332401.728968") dt = datetime(2019, 12, 3, 0, 20, 1, 728968) - self.assertEqual(self.formatter._format_token(dt, "X"), "1575332401728968") + self.assertEqual(self.formatter._format_token(dt, "x"), "1575332401728968") def test_timezone(self): From 38b81db7cae708a698d3910f9ebeca0edf85b4a0 Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 20:00:36 -0500 Subject: [PATCH 06/14] Update formatter.py --- arrow/formatter.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index 843480004..2d858ca94 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -100,10 +100,8 @@ def _format_token(self, dt, token): if token == "X": microsecond = str(int(dt.microsecond)) return str(calendar.timegm(dt.utctimetuple())) + '.' + microsecond - if token == "x": microsecond = str(int(dt.microsecond)) - return str(calendar.timegm(dt.utctimetuple())) + microsecond.rstrip('0') if token == "ZZZ": From 17b335630147710d5f59990f71ba47a8d08448b2 Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 20:07:18 -0500 Subject: [PATCH 07/14] Update formatter.py --- arrow/formatter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index 2d858ca94..fb8f4233c 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -99,10 +99,10 @@ def _format_token(self, dt, token): if token == "X": microsecond = str(int(dt.microsecond)) - return str(calendar.timegm(dt.utctimetuple())) + '.' + microsecond + return str(calendar.timegm(dt.utctimetuple())) + "." + microsecond if token == "x": microsecond = str(int(dt.microsecond)) - return str(calendar.timegm(dt.utctimetuple())) + microsecond.rstrip('0') + return str(calendar.timegm(dt.utctimetuple())) + microsecond.rstrip("0") if token == "ZZZ": return dt.tzname() From 8d710771186126acab2939b9578ef387b0308f08 Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 20:17:08 -0500 Subject: [PATCH 08/14] Update formatter_tests.py --- tests/formatter_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index 712d57eb0..ddfef4c2f 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -104,9 +104,10 @@ def test_sub_second(self): self.assertEqual(self.formatter._format_token(dt, "S"), "0") def test_timestamp(self): + dt = datetime(2019, 12, 3, 0, 20, 1, 728968) self.assertEqual(self.formatter._format_token(dt, "X"), "1575332401.728968") - + dt = datetime(2019, 12, 3, 0, 20, 1, 728968) self.assertEqual(self.formatter._format_token(dt, "x"), "1575332401728968") From 4b9fb7659d85a76343b02960e91924d4e7c36c19 Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 20:31:24 -0500 Subject: [PATCH 09/14] Update formatter_tests.py --- tests/formatter_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index ddfef4c2f..18f9bca95 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -110,7 +110,7 @@ def test_timestamp(self): dt = datetime(2019, 12, 3, 0, 20, 1, 728968) self.assertEqual(self.formatter._format_token(dt, "x"), "1575332401728968") - + def test_timezone(self): dt = datetime.utcnow().replace(tzinfo=dateutil_tz.gettz("US/Pacific")) From d4932263e2faaf780201bdbe320380f1def82a6e Mon Sep 17 00:00:00 2001 From: zihan Date: Mon, 2 Dec 2019 20:40:40 -0500 Subject: [PATCH 10/14] Update formatter_tests.py --- tests/formatter_tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index 18f9bca95..04462217b 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import time from datetime import datetime import pytz From 763eb9b0b29872f94f54164fc3a8ead72a68c74e Mon Sep 17 00:00:00 2001 From: zihan Date: Sun, 22 Dec 2019 23:32:47 -0500 Subject: [PATCH 11/14] Update formatter.py --- arrow/formatter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index fb8f4233c..9c0462b23 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -16,7 +16,7 @@ class DateTimeFormatter(object): # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X)" + r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x)" ) def __init__(self, locale="en_us"): From 4baa0363e29a97e4abdb8de39325ec43975648bf Mon Sep 17 00:00:00 2001 From: zihan Date: Sun, 29 Dec 2019 19:07:15 -0500 Subject: [PATCH 12/14] Update formatter.py --- arrow/formatter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index 9c0462b23..feb1cf25c 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -16,7 +16,7 @@ class DateTimeFormatter(object): # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X|x)" + r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|x|X)" ) def __init__(self, locale="en_us"): From e17c9e6c2d977f6c22a37c6a1cac318d4802fae9 Mon Sep 17 00:00:00 2001 From: zihan Date: Sun, 29 Dec 2019 19:09:28 -0500 Subject: [PATCH 13/14] Update formatter.py --- arrow/formatter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index feb1cf25c..28597f899 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -16,7 +16,7 @@ class DateTimeFormatter(object): # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|x|X)" + r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|x|A|X)" ) def __init__(self, locale="en_us"): From a2f168ec32b43035aff7f767aec534a3c20f7a9f Mon Sep 17 00:00:00 2001 From: zihan Date: Sun, 29 Dec 2019 19:10:01 -0500 Subject: [PATCH 14/14] Update formatter.py --- arrow/formatter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow/formatter.py b/arrow/formatter.py index 28597f899..fb8f4233c 100644 --- a/arrow/formatter.py +++ b/arrow/formatter.py @@ -16,7 +16,7 @@ class DateTimeFormatter(object): # emulated in Python's re library, see https://stackoverflow.com/a/13577411/2701578 # TODO: test against full timezone DB _FORMAT_RE = re.compile( - r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|x|A|X)" + r"(\[(?:(?=(?P[^]]))(?P=literal))*\]|YYY?Y?|MM?M?M?|Do|DD?D?D?|d?dd?d?|HH?|hh?|mm?|ss?|SS?S?S?S?S?|ZZ?Z?|a|A|X)" ) def __init__(self, locale="en_us"):