aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2020-10-02 09:07:49 +0200
committerElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2020-10-02 09:07:49 +0200
commitb75c00bf5a7f650ff53a407b47a96407ac277d8e (patch)
tree9a6d77b2bad5f61d883469d0cebeb1dcb4eb30c0
parente0f8012431f6e5359f4f03b3d3a36403adff85bf (diff)
Add date and datetime types, enforce timestamps to be unix timestamps
-rw-r--r--docs/field_types.rst4
-rw-r--r--lesana/types.py51
-rw-r--r--tests/test_types.py57
3 files changed, 109 insertions, 3 deletions
diff --git a/docs/field_types.rst b/docs/field_types.rst
index baf2c5e..81e86ab 100644
--- a/docs/field_types.rst
+++ b/docs/field_types.rst
@@ -14,6 +14,10 @@ decimal:
.
timestamp:
.
+datetime:
+ .
+date:
+ .
boolean:
.
file:
diff --git a/lesana/types.py b/lesana/types.py
index 4d3910c..e5c556c 100644
--- a/lesana/types.py
+++ b/lesana/types.py
@@ -105,16 +105,39 @@ class LesanaDecimal(LesanaType):
class LesanaTimestamp(LesanaType):
"""
- A datetime
+ A unix timestamp
"""
name = "timestamp"
def load(self, data):
if not data:
return data
- if isinstance(data, datetime.datetime) or \
- isinstance(data, datetime.date):
+ if isinstance(data, datetime.datetime):
+ return data
+ try:
+ return datetime.datetime.fromtimestamp(int(data))
+ except (TypeError, ValueError):
+ raise LesanaValueError(
+ "Invalid value for timestamp field: {}".format(data)
+ )
+
+ def empty(self):
+ return None
+
+
+class LesanaDatetime(LesanaType):
+ """
+ A datetime
+ """
+ name = "datetime"
+
+ def load(self, data):
+ if not data:
+ return data
+ if isinstance(data, datetime.datetime):
return data
+ if isinstance(data, datetime.date):
+ return datetime.datetime(data.year, data.month, data.day)
try:
return dateutil.parser.parse(data)
except dateutil.parser.ParserError:
@@ -126,6 +149,28 @@ class LesanaTimestamp(LesanaType):
return None
+class LesanaDate(LesanaType):
+ """
+ A date
+ """
+ name = "date"
+
+ def load(self, data):
+ if not data:
+ return data
+ if isinstance(data, datetime.date):
+ return data
+ try:
+ return dateutil.parser.parse(data)
+ except dateutil.parser.ParserError:
+ raise LesanaValueError(
+ "Invalid value for date field: {}".format(data)
+ )
+
+ def empty(self):
+ return None
+
+
class LesanaBoolean(LesanaType):
"""
A boolean value
diff --git a/tests/test_types.py b/tests/test_types.py
index cc2ff3b..2d6b744 100644
--- a/tests/test_types.py
+++ b/tests/test_types.py
@@ -119,6 +119,63 @@ class testTypes(unittest.TestCase):
v = checker.load(now)
self.assertEqual(v, now)
+ v = checker.load("1600000000")
+ self.assertEqual(v, datetime.datetime(2020, 9, 13, 14, 26, 40))
+
+ today = datetime.date.today()
+ for d in (
+ today,
+ "today",
+ "2020-13-01", "2020-01-01",
+ "2020-01-01 10:00"
+ ):
+ with self.assertRaises(types.LesanaValueError):
+ checker.load(d)
+
+ v = checker.load(None)
+ self.assertEqual(v, None)
+
+ def test_datetime(self):
+ checker = types.LesanaDatetime()
+
+ v = checker.empty()
+ self.assertEqual(v, None)
+
+ now = datetime.datetime.now()
+ v = checker.load(now)
+ self.assertEqual(v, now)
+
+ today = datetime.date.today()
+ v = checker.load(today)
+ self.assertIsInstance(v, datetime.datetime)
+ for part in ('year', 'month', 'day'):
+ self.assertEqual(getattr(v, part), getattr(today, part))
+
+ v = checker.load("2020-01-01")
+ self.assertEqual(v, datetime.datetime(2020, 1, 1))
+
+ v = checker.load("2020-01-01 10:00")
+ self.assertEqual(v, datetime.datetime(2020, 1, 1, 10, 0))
+
+ for d in ("today", "2020-13-01"):
+ with self.assertRaises(types.LesanaValueError):
+ checker.load(d)
+
+ v = checker.load(None)
+ self.assertEqual(v, None)
+
+ def test_date(self):
+ checker = types.LesanaDate()
+
+ v = checker.empty()
+ self.assertEqual(v, None)
+
+ now = datetime.datetime.now()
+ v = checker.load(now)
+ self.assertIsInstance(v, datetime.date)
+ for part in ('year', 'month', 'day'):
+ self.assertEqual(getattr(v, part), getattr(now, part))
+
today = datetime.date.today()
v = checker.load(today)
self.assertEqual(v, today)