Skip to content

Commit d94dd11

Browse files
ghuronclaude
andcommitted
Fix time serializer to always emit precision and avoid 00 day/month
- Always include precision in time JSON, defaulting to 11 (day) if not stored - Replace 00 month/day with 01 to satisfy Wikibase API validation - Support /precision suffix embedded in full timestamp strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7cf0f47 commit d94dd11

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

src/wdpy/snak.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,17 @@ def json(self) -> str:
9696
if len(v) > 1 and v[1]: res['value']['lowerBound'] = v[1]
9797
if len(v) > 2 and v[2]: res['value']['upperBound'] = v[2]
9898
case 'time':
99-
res = {'type': 'time', 'value': {'time': f"+{v[0][:4]}-{v[0][4:6]}"
100-
f"-{v[0][6:]}T00:00:00Z" if len(v[0]) == 8 else v[0],
101-
'timezone': 0, 'before': 0, 'after': 0}}
102-
if len(v) > 1 and v[1]:
103-
res['value']['precision'] = int(v[1]) if v[1].isdigit() else v[1]
99+
time_str, _, suffix = v[0].partition('/')
100+
precision = (int(suffix) if suffix.isdigit() else
101+
int(v[1]) if len(v) > 1 and v[1] and v[1].isdigit() else 11)
102+
if len(time_str) == 8:
103+
mo = time_str[4:6] if time_str[4:6] != '00' else '01'
104+
day = time_str[6:] if time_str[6:] != '00' else '01'
105+
time_out = f"+{time_str[:4]}-{mo}-{day}T00:00:00Z"
106+
else:
107+
time_out = time_str
108+
res = {'type': 'time', 'value': {'time': time_out,
109+
'timezone': 0, 'before': 0, 'after': 0, 'precision': precision}}
104110
if len(v) > 2 and v[2]:
105111
res['value']['calendarmodel'] = (f"http://www.wikidata.org/entity"
106112
f"/{v[2]}" if not v[2].startswith('http') else v[2])

tests/unit/test_snak.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,19 @@ def test_time(self, *_):
162162
snak, expected = ETHALONS['time']
163163
self.assertEqual(json.loads(snak.json()), expected)
164164

165+
@mock.patch.object(Snak, 'type_of', return_value='time')
166+
def test_time_no_precision_defaults_to_11(self, *_):
167+
snak = Snak('P813', ('20240526',))
168+
payload = json.loads(snak.json())
169+
self.assertEqual(11, payload['datavalue']['value']['precision'])
170+
171+
@mock.patch.object(Snak, 'type_of', return_value='time')
172+
def test_time_precision_suffix_in_time_string(self, *_):
173+
snak = Snak('P813', ('+2013-01-00T00:00:00Z/10',))
174+
payload = json.loads(snak.json())
175+
self.assertEqual(10, payload['datavalue']['value']['precision'])
176+
self.assertEqual('+2013-01-00T00:00:00Z', payload['datavalue']['value']['time'])
177+
165178
def test_monolingual(self, *_):
166179
snak, expected = ETHALONS['monolingual']
167180
self.assertEqual(json.loads(snak.json()), expected)

0 commit comments

Comments
 (0)