From 091498e3c77ac098ea703650fde83c54b6aab5d5 Mon Sep 17 00:00:00 2001
From: Valentin Lorentz <vlorentz@softwareheritage.org>
Date: Tue, 5 May 2020 12:03:39 +0200
Subject: [PATCH] Make aware_datetimes() generate only ISO8601-encodable
 datetimes.

---
 swh/model/hypothesis_strategies.py            | 12 +++++++++++-
 swh/model/tests/test_hypothesis_strategies.py | 10 ++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/swh/model/hypothesis_strategies.py b/swh/model/hypothesis_strategies.py
index d1938522..448487a8 100644
--- a/swh/model/hypothesis_strategies.py
+++ b/swh/model/hypothesis_strategies.py
@@ -72,7 +72,17 @@ def sha1():
 
 
 def aware_datetimes():
-    return datetimes(timezones=timezones())
+    # datetimes in Software Heritage are not used for software artifacts
+    # (which may be much older than 2000), but only for objects like scheduler
+    # task runs, and origin visits, which were created by Software Heritage,
+    # so at least in 2015.
+    # We're forbidding old datetimes, because until 1956, many timezones had seconds
+    # in their "UTC offsets" (see
+    # <https://en.wikipedia.org/wiki/Time_zone#Worldwide_time_zones>), which is not
+    # encodable in ISO8601; and we need our datetimes to be ISO8601-encodable in the
+    # RPC protocol
+    min_value = datetime.datetime(2000, 1, 1, 0, 0, 0)
+    return datetimes(min_value=min_value, timezones=timezones())
 
 
 @composite
diff --git a/swh/model/tests/test_hypothesis_strategies.py b/swh/model/tests/test_hypothesis_strategies.py
index 2df2d7a2..1622b3c7 100644
--- a/swh/model/tests/test_hypothesis_strategies.py
+++ b/swh/model/tests/test_hypothesis_strategies.py
@@ -6,10 +6,12 @@
 import datetime
 
 import attr
+import iso8601
 from hypothesis import given, settings
 
 from swh.model.hashutil import DEFAULT_ALGORITHMS
 from swh.model.hypothesis_strategies import (
+    aware_datetimes,
     objects,
     object_dicts,
     contents,
@@ -93,6 +95,14 @@ def test_dicts_generation(obj_type_and_obj):
             assert branch is None or branch["target_type"] in target_types
 
 
+@given(aware_datetimes())
+def test_datetimes(dt):
+    # Checks this doesn't raise an error, eg. about seconds in the TZ offset
+    iso8601.parse_date(dt.isoformat())
+
+    assert dt.tzinfo is not None
+
+
 @given(object_dicts(split_content=False))
 def test_dicts_generation_merged_content(obj_type_and_obj):
     # we should never generate a "skipped_content" here
-- 
GitLab