diff --git a/swh/model/identifiers.py b/swh/model/identifiers.py
index cf3b3265f1e0392b76430b880ffaee2c8cd2171b..c53513ae6bfbb9798a0845b7d1b38c2399b8c62a 100644
--- a/swh/model/identifiers.py
+++ b/swh/model/identifiers.py
@@ -171,19 +171,21 @@ def format_date(date):
     microseconds (postgres type "datetime with timezone").
 
     Therefore, we print timestamps with no microseconds as integers, and
-    timestamps with microseconds as floating point values.
+    timestamps with microseconds as floating point values. We elide the
+    trailing zeroes from microsecond values, to "future-proof" our
+    representation if we ever need more precision in timestamps.
 
     """
-    if isinstance(date, datetime.datetime):
-        if date.microsecond == 0:
-            date = int(date.timestamp())
-        else:
-            date = date.timestamp()
-        return str(date).encode()
+    if not isinstance(date, dict):
+        raise ValueError('format_date only supports dicts, %r received' % date)
+
+    seconds = date.get('seconds', 0)
+    microseconds = date.get('microseconds', 0)
+    if not microseconds:
+        return str(seconds).encode()
     else:
-        if date == int(date):
-            date = int(date)
-        return str(date).encode()
+        float_value = ('%d.%06d' % (seconds, microseconds))
+        return float_value.rstrip('0').encode()
 
 
 @lru_cache()
@@ -221,8 +223,9 @@ def normalize_timestamp(time_representation):
 
     Returns: a normalized dictionary with three keys
 
-     - timestamp: a number of seconds since the UNIX epoch (1970-01-01 at 00:00
-       UTC)
+     - timestamp: a dict with two optional keys:
+        - seconds: the integral number of seconds since the UNIX epoch
+        - microseconds: the integral number of microseconds
      - offset: the timezone offset as a number of minutes relative to UTC
      - negative_utc: a boolean representing whether the offset is -0000 when
        offset = 0.
@@ -235,12 +238,23 @@ def normalize_timestamp(time_representation):
     negative_utc = False
 
     if isinstance(time_representation, dict):
-        timestamp = time_representation['timestamp']
+        ts = time_representation['timestamp']
+        if isinstance(ts, dict):
+            seconds = ts.get('seconds', 0)
+            microseconds = ts.get('microseconds', 0)
+        elif isinstance(ts, int):
+            seconds = ts
+            microseconds = 0
+        else:
+            raise ValueError(
+                'normalize_timestamp received non-integer timestamp member:'
+                ' %r' % ts)
         offset = time_representation['offset']
         if 'negative_utc' in time_representation:
             negative_utc = time_representation['negative_utc']
     elif isinstance(time_representation, datetime.datetime):
-        timestamp = time_representation.timestamp()
+        seconds = int(time_representation.timestamp())
+        microseconds = time_representation.microsecond
         utcoffset = time_representation.utcoffset()
         if utcoffset is None:
             raise ValueError(
@@ -250,12 +264,20 @@ def normalize_timestamp(time_representation):
         # utcoffset is an integer number of minutes
         seconds_offset = utcoffset.total_seconds()
         offset = int(seconds_offset) // 60
-    else:
-        timestamp = time_representation
+    elif isinstance(time_representation, int):
+        seconds = time_representation
+        microseconds = 0
         offset = 0
+    else:
+        raise ValueError(
+            'normalize_timestamp received non-integer timestamp:'
+            ' %r' % time_representation)
 
     return {
-        'timestamp': timestamp,
+        'timestamp': {
+            'seconds': seconds,
+            'microseconds': microseconds,
+        },
         'offset': offset,
         'negative_utc': negative_utc,
     }
diff --git a/swh/model/tests/test_identifiers.py b/swh/model/tests/test_identifiers.py
index e1adfea34f08ac419af4fc424fb4460e3eaabc6e..16a34bb9c76561bde5e97e42e2298f973b37e75e 100644
--- a/swh/model/tests/test_identifiers.py
+++ b/swh/model/tests/test_identifiers.py
@@ -55,15 +55,23 @@ class UtilityFunctionsIdentifier(unittest.TestCase):
 
 class UtilityFunctionsDateOffset(unittest.TestCase):
     def setUp(self):
-        self.date = datetime.datetime(
-            2015, 11, 22, 16, 33, 56, tzinfo=datetime.timezone.utc)
-        self.date_int = int(self.date.timestamp())
-        self.date_repr = b'1448210036'
-
-        self.date_microseconds = datetime.datetime(
-            2015, 11, 22, 16, 33, 56, 2342, tzinfo=datetime.timezone.utc)
-        self.date_microseconds_float = self.date_microseconds.timestamp()
-        self.date_microseconds_repr = b'1448210036.002342'
+        self.dates = {
+            b'1448210036': {
+                'seconds': 1448210036,
+                'microseconds': 0,
+            },
+            b'1448210036.002342': {
+                'seconds': 1448210036,
+                'microseconds': 2342,
+            },
+            b'1448210036.12': {
+                'seconds': 1448210036,
+                'microseconds': 120000,
+            }
+        }
+        self.broken_dates = [
+            1448210036.12,
+        ]
 
         self.offsets = {
             0: b'+0000',
@@ -73,12 +81,14 @@ class UtilityFunctionsDateOffset(unittest.TestCase):
 
     @istest
     def format_date(self):
-        for date in [self.date, self.date_int]:
-            self.assertEqual(identifiers.format_date(date), self.date_repr)
+        for date_repr, date in self.dates.items():
+            self.assertEqual(identifiers.format_date(date), date_repr)
 
-        for date in [self.date_microseconds, self.date_microseconds_float]:
-            self.assertEqual(identifiers.format_date(date),
-                             self.date_microseconds_repr)
+    @istest
+    def format_date_fail(self):
+        for date in self.broken_dates:
+            with self.assertRaises(ValueError):
+                identifiers.format_date(date)
 
     @istest
     def format_offset(self):
@@ -285,7 +295,7 @@ dg1KdHOa34shrKDaOVzW
                 'email': b'robot@softwareheritage.org',
             },
             'date': {
-                'timestamp': 1437047495.0,
+                'timestamp': {'seconds': 1437047495},
                 'offset': 0,
                 'negative_utc': False,
             },
@@ -349,7 +359,7 @@ dg1KdHOa34shrKDaOVzW
                 'fullname': b'Jiang Xin <worldhello.net@gmail.com>',
             },
             'date': {
-                'timestamp': '1428538899',
+                'timestamp': 1428538899,
                 'offset': 480,
             },
             'committer': {
@@ -357,7 +367,7 @@ dg1KdHOa34shrKDaOVzW
                 'email': b'worldhello.net@gmail.com',
             },
             'committer_date': {
-                'timestamp': '1428538899',
+                'timestamp': 1428538899,
                 'offset': 480,
             },
             'metadata': {
@@ -383,7 +393,7 @@ dg1KdHOa34shrKDaOVzW
                 'fullname': b'Jiang Xin <worldhello.net@gmail.com>',
             },
             'date': {
-                'timestamp': '1428538899',
+                'timestamp': 1428538899,
                 'offset': 480,
             },
             'committer': {
@@ -391,7 +401,7 @@ dg1KdHOa34shrKDaOVzW
                 'email': b'worldhello.net@gmail.com',
             },
             'committer_date': {
-                'timestamp': '1428538899',
+                'timestamp': 1428538899,
                 'offset': 480,
             },
             'message': None,
@@ -408,7 +418,7 @@ dg1KdHOa34shrKDaOVzW
                 'fullname': b'Jiang Xin <worldhello.net@gmail.com>',
             },
             'date': {
-                'timestamp': '1428538899',
+                'timestamp': 1428538899,
                 'offset': 480,
             },
             'committer': {
@@ -416,7 +426,7 @@ dg1KdHOa34shrKDaOVzW
                 'email': b'worldhello.net@gmail.com',
             },
             'committer_date': {
-                'timestamp': '1428538899',
+                'timestamp': 1428538899,
                 'offset': 480,
             },
             'message': b'',
@@ -592,7 +602,7 @@ o6X/3T+vm8K3bf3driRr34c=
             'target': '54e9abca4c77421e2921f5f156c9fe4a9f7441c7',
             'target_type': 'revision',
             'date': {
-                'timestamp': 1225281976.0,
+                'timestamp': {'seconds': 1225281976},
                 'offset': 0,
                 'negative_utc': True,
             },