Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion python_wikibase/data_types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
from python_wikibase.data_types.geo_location import GeoLocation
from python_wikibase.data_types.quantity import Quantity
from python_wikibase.data_types.string_value import StringValue
from python_wikibase.data_types.time import Time

__all__ = ["ExternalId", "GeoLocation", "Quantity", "StringValue"]
__all__ = ["ExternalId", "GeoLocation", "Quantity", "StringValue", "Time"]
2 changes: 1 addition & 1 deletion python_wikibase/data_types/data_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def unmarshal_data_value(py_wb, main_snak):
elif data_type == "tabular-data":
raise NotImplementedError # TODO
elif data_type == "time":
raise NotImplementedError # TODO
return py_wb.Time().unmarshal(data_value)
elif data_type == "url":
raise NotImplementedError # TODO
elif data_type == "wikibase-form":
Expand Down
76 changes: 76 additions & 0 deletions python_wikibase/data_types/time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import collections
import datetime

from python_wikibase.data_types.data_type import DataType


class DataTypeException(BaseException):
pass

# Largely inspired from https://github.com/dahlia/wikidata/blob/master/wikidata/datavalue.py


class Time(DataType):
def __init__(self, py_wb, api, language):
super().__init__(py_wb, api, language)
self.value = None

def __str__(self):
return self.value.isoformat()

def unmarshal(self, data_value):
value = data_value["value"]

# See https://www.mediawiki.org/wiki/Wikibase/DataModel/JSON#time
# for property to extract from data_value

time = value['time']
# Strip '+' at beginning of string and 'Z' at the end
time = time[1:-1]

tz = value['timezone']
# Don't take in account 'before' and 'after' property
precision = value['precision']

if precision == 11:
self.value = datetime.date.fromisoformat(time[:-9])
elif precision == 14:
val = datetime.datetime.fromisoformat(time)
val.replace(tzinfo=datetime.timezone(offset=datetime.timedelta(minutes=tz)))
self.value = val
return self

def marshal(self):

common_properties = {
"timezone": 0,
"before": 0,
"after": 0,
"calendarmodel": "http:\/\/www.wikidata.org\/entity\/Q1985727"
}

if isinstance(self.value, datetime.date):
return {
**common_properties,
"time": "+{}T00:00:00Z".format(self.value.isoformat()),
"precision": 11
}
elif isinstance(self.value, datetime.datetime):
dt = self.value.astimezone(tz=datetime.timezone.utc)
return {
**common_properties,
"time": "+{}Z".format(iso_str[:19]),
"precision": 14
}

def create(self, value):
if isinstance(value, datetime.datetime):
# consider as utc if timezone info is missing
if value.tzinfo is None:
value = value.replace(tzinfo=datetime.timezone.utc)

elif not isinstance(value, datetime.date):
raise DataTypeException("Unknown value type {!r}".format(value))
self.value = value

return self
5 changes: 4 additions & 1 deletion python_wikibase/python_wikibase.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
Reference,
References,
)
from python_wikibase.data_types import ExternalId, GeoLocation, Quantity, StringValue
from python_wikibase.data_types import ExternalId, GeoLocation, Quantity, StringValue, Time

DEFAULT_CONFIG = {
"api_url": "https://www.wikidata.org/w/api.php",
Expand Down Expand Up @@ -96,3 +96,6 @@ def Quantity(self):

def StringValue(self):
return StringValue(self, self.api, self.language)

def Time(self):
return Time(self, self.api, self.language)
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
PROP_ITEM_LABEL,
PROP_LABEL,
PROP_QUANTITY_LABEL,
PROP_TIME_LABEL,
STRING_VALUE,
)

Expand Down Expand Up @@ -110,8 +111,16 @@ def prop_quantity(py_wb):
prop.delete()


@pytest.fixture(scope="function")
def prop_time(py_wb):
prop = py_wb.Property().create(PROP_TIME_LABEL, data_type="Time")
assert prop.label.get(LANGUAGE) == PROP_TIME_LABEL
yield prop
prop.delete()

# Values


@pytest.fixture(scope="function")
def string_value(py_wb):
string_value = py_wb.StringValue().create(STRING_VALUE)
Expand Down
1 change: 1 addition & 0 deletions tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
PROP_ITEM_LABEL = "Wikibase item property"
PROP_GEO_LOCATION_LABEL = "GeoLocation property"
PROP_QUANTITY_LABEL = "Quantity property"
PROP_TIME_LABEL = "Time property"

STRING_VALUE = "String value"
10 changes: 10 additions & 0 deletions tests/test_claim.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,13 @@ def test_quantity_with_unit(self, py_wb, item, prop_quantity, item_unit):
assert claim.value.amount == amount
assert float(claim.value) == amount
assert claim.value.marshal() == quantity.marshal()

# Time

def test_time(self, py_wb, item, prop_time):
date = datetime.date.fromisoformart("2012-05-12")
time_ = py_wb.Time().create(date_str)
claim = item.claims.add(prop_time, time_)
assert claim.property.data_type == "Time"
assert claim.value.date == date
assert claim.value.marshal() == time_.marshal()