Package: timefuncs
RDFlib OWL TIME FunctionsThis Python package implements functions to ascertain the temporal relations of objects in RDF graphs.This package invents SPARQL functions that are based on logic provided inOWL TIMEand are named similarly to TIME's Temporal Entity's predicates, for example, the functionisBefore()correlates totime:before, i.e.isBefore(a, b)will test to see iftime:beforeshould be applied between objecta&b.The functions are made available as functions inRDFlib's SPARQL implementation where they can be called by IRI, e.g.isBefore(a, b)is calledtfun:isBefore(?a, ?b). All functions are posed as questions, "is before", and return an RDF literaltrueorfalse.This repository also contains a formal declaration of the functions that this package implements as aSKOSvocabulary. See theVocabularysection below.InstallationNormal Python package installation e.g. from PyPI:pip install timefuncs.This package's only non-standard dependency isRDFlib.UseThese functions are implemented in RDFlib Python in the filetimefuncts/funcs.pyand are imported intotimefuncs/__init__.pyand registered there in RDFlib as SPARQL extension functions with their IRIs.This means they can be used like this (full working script):fromrdflibimportGraphfromtimefuncsimportTFUNdata="""PREFIX : <http://example.com/>PREFIX time: <http://www.w3.org/2006/time#>:a01 a time:TemporalEntity .:b01 a time:TemporalEntity .:c01 a time:TemporalEntity .:d01 a time:TemporalEntity .:a01 time:before :c01 .:b01 time:after :c01 ."""g=Graph().parse(data=data)q="""PREFIX tfun: <https://w3id.org/timefuncs/>SELECT *WHERE {?x a time:TemporalEntity .?y a time:TemporalEntity .FILTER tfun:isBefore(?x, ?y)}"""forring.query(q):print(f"{r['x']}is before{r['y']}")The above stript outputs:http://example.com/a01isbeforehttp://example.com/b01
http://example.com/a01isbeforehttp://example.com/c01
http://example.com/b01isbeforehttp://example.com/c01The above script is run using an environment that has had the time functions registered with its copy of rdflib (perhaps by runningpip install timefuncs) so that there is no need to import anything other than rdfib and the time functions namespace (from timefuncs import TFUN). It may appear that the namespace is not used but it is, internally! No need to re-declaretfun:as aPREFIXin the SPARQL query...The time function used here,tfun:isBefore, is called as a filter function to returntruewhen the first given object, here?xisbeforethe second given object,?y.This example uses a pretty open-ended graph pattern match (`?x ?p ?y).Working with Reasoning / InferencingThese functions don't assume that any reasoning has been carried out on data and will correctly interprettime:before/time:afterand similar inverses, transitive relations (chains of properties) and so on. But there are limits: you will always be able to invent highly complex relations betweentime:TemporalEntityinstances that these functions won't correctly work with.To work with highly complex data, try reasoning over your data first with OWL TIME's axioms before running these functions. To do this, you need a tool that can calculate OWL "RL" inferences, such asrdflib's OWL-RL. Many triplestores have OWL-RL reasoning capability built-in or as add ons.FunctionsFunctions in this package are implemented as SPARQL extension functions with the namespacehttps://w3id.org/timefuncs/, e.g.isBefore()'s full IRI ishttps://w3id.org/timefuncs/isBefore.Python implementations are named the same as the SPARQL functions, but in snake_case, not camelCase, e.g. SPARQL'sisBefore()is implemented in Python'sis_before().Functions implemented so far, and their corresponding TIME relations:SPARQLParametersTIME predicatesNotestfun:contains(a, b)time:Intervaltime:Intervaltime:intervalContainsinv.time:intervalDuringequivalent totfun:isContainedBy(b, a)tfun:finishes(a, b)time:Intervaltime:Intervaltime:intervalFinishesinv.time:intervalFinishedBynottime:disjointequivalent totfun:isFinishedBy(b, a)tfun:hasDuring(a, b)time:Intervaltime:Intervalalias forcontains(a, b)tfun:hasInside(a, b)time:Intervaltime:Instanttime:insidenottime:beforenottime:afterequivalent totfun:isInside(b, a)tfun:isAfter(a, b)time:TemporalEntitytime:TemporalEntitytime:afterinv.time:beforeequivalent totfun:isBefore(b, a)tfun:isBefore(a, b)time:TemporalEntitytime:TemporalEntitytime:beforeinv.time:afterequivalent totfun:isAfter(b, a)tfun:isContainedBy(a, b)time:Intervaltime:Intervaltime:intervalDuringinv.time:intervalContainsequivalent totfun:contains(b, a)tfun:isDuring(a, b)time:Intervaltime:Intervalalias forisContainedBy(a, b)tfun:isFinishedBy(a, b)time:Intervaltime:Intervaltime:intervalFinishedByinv.time:intervalFinishesnottime:disjointequivalent totfun:finishes(b, a)tfun:isInside(a, b)time:Instanttime:Intervalinv.time:insidenottime:afternottime:beforeequivalent totfun:hasInside(b, a)tfun:isStartedBy(a, b)time:Intervaltime:Intervaltime:isStartedByinv.time:startstfun:starts(b, a)tfun:starts(a, b)time:Intervaltime:Intervaltime:startsinv.time:isStartedBytfun:isStartedBy(b, a)These functions are yet to be implemented:SPARQLNotestfun:hasBeginning(a, b)tfun:hasEnd(a, b)tfun:isFinishedBy(a, b)tfun:isBeginningOf(a, b)tfun:isDisjoint(a, b)tfun:isEndOf(a, b)tfun:isEquals(a, b)tfun:isIn(a, b)tfun:isMetBy(a, b)tfun:isNotDisjoint(a, b)tfun:isOverlappedBy(a, b)tfun:isStartedBy(a, b)tfun:meets(a, b)tfun:overlaps(a, b)Non-TIME functionsThe followingproposedfunctions are inspired by OWL TIME but not directly related to its predicates or classes:SPARQLNotestfun:hasTemporalRelation(a, b)Returns the temporal relation betweena&bMay have to run sequences of the otherisDisjoint(a, b)functions to determinetfun:toUNIXTime(a)Returns a UNIX Time representation of axsd:dateTimeorxsd:dateTimeStampMay be extended for other TRS inputstfun:toXSDDateTimeStamp(a)Returns an XSDxsd:dateTimeStamp(UTC) representation of a UNIX timeMay be extended for other TRS inputsImplementation logicFunctions implemented test for every conceivable way that a temporal relation may be found to be true in given data. For example,isBefore(a, b)will return true if:the predicatetime:beforeis given betweena&b, or any chain of objectsa...n...bthe predicatetime:afteris given betweenb&a, or any chain of objectsb...n...aany chain oftime:before&time:afterlinksa&b, all pointing in the right directionsthe end ofais declared as being beforebor the start ofbi.e.  for<a> time:hasEnd <a_end> .and<b> time:hasBeginning <b_beginning> .,isBefore(a, b)istrueif<a_end> time:before <b_beginning>the start ofbis declared as being afteraor the end ofaacan be calculated as being beforeb, based on their instantaneous times or start and end timesi.e. for<a> time:inXSDDateTimeStamp <a_xsd> .and<b> time:inXSDDateTimeStamp <b_xsd> .or<a> time:hasEnd/time:inXSDDateTimeStamp <a_xsd> .and<b> time:hasEnd/time:inXSDDateTimeStamp <b_xsd> .,isBefore(a, b)istrueif<a_xsd> <b_xsd>VocabularyThe time functions, both implemented and to-be implemented, are listed in a SKOS vocabulary, the source files for which are given in thevoc/folder within this repository. The vocabulary is presented online in both RDF (turtle) and HTML (Markdown) formats from these source files, accessible via the namespace IRI:https://w3id.org/timefuncs/voc- HTMLhttps://w3id.org/timefuncs/voc.ttl- RDFEach function's IRI resolves to its Concept entry in the vocbaulary, for example,https://w3id.org/timefuncs/isContainedBy-->https://github.com/RDFLib/timefuncs/blob/master/voc/timefuncs.md#is-contained-by.(The Markdown is auto-generated from the RDF usingpyLODE)TestingAll tests are intests/and implemented usingpytest.There are individual tests for each function, e.g.tests/test_is_before.pyforisBefore()as well as a test file to rn all tests againts OWL TIME'stest suite):tests/test_test_suite.py.ContributingVia GitHub, Issues & Pull Requests:https://github.com/rdflib/timefuncsLicenseThis code is licensed with the BSD 3-clause license as perLICENSEwhich is the same license as used forrdflib.Citation@software{https://github.com/rdflib/timefuncs,author={{Nicholas J. Car}},title={RDFlib OWL TIME Functions},version={0.0.2},date={2021},url={https://github.com/rdflib/timefuncs}}ContactCreator & maintainer:Nicholas J. CarData System ArchitectSURROUND Australia Pty Ltdnicholas.car@surroundaustrlaia.comandAdjunct Senior LecturerCollege of Engineering & Computer ScienceAustralian National Universitynicholas.car@anu.edu.auhttps://orcid.org/0000-0002-8742-7730