@prefix qudt: <http://qudt.org/schema/qudt/> .
@prefix quantitykind: <http://qudt.org/vocab/quantitykind/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

# Shapes over W3C OWL-Time. No local classes: the temporal entity, relation and
# coordinate layers are all reused from time:.

time:Instant
    a sh:NodeShape ;
    sh:targetClass time:Instant ;
    sh:message "An instant reads at most one time position." ;
    sh:property [
        sh:path time:inTimePosition ;
        sh:maxCount 1 ;
        sh:nodeKind sh:BlankNodeOrIRI ;
        sh:class time:TimePosition
    ] ;
    sh:property [
        sh:path time:inXSDDateTimeStamp ;
        sh:maxCount 1 ;
        sh:datatype xsd:dateTimeStamp
    ] .

time:TimePosition
    a sh:NodeShape ;
    sh:targetClass time:TimePosition ;
    sh:message "A time position is a number read against exactly one clock (TRS)." ;
    sh:property [
        sh:path time:hasTRS ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:IRI ;
        sh:class time:TRS
    ] ;
    sh:property [
        sh:path time:numericPosition ;
        sh:maxCount 1 ;
        sh:datatype xsd:double
    ] .

time:ProperInterval
    a sh:NodeShape ;
    sh:targetClass time:ProperInterval ;
    sh:message "An interval spans exactly one beginning and one ending instant, and carries at most one duration." ;
    sh:property [
        sh:path time:hasBeginning ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:BlankNodeOrIRI ;
        sh:class time:Instant
    ] ;
    sh:property [
        sh:path time:hasEnd ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:BlankNodeOrIRI ;
        sh:class time:Instant
    ] ;
    sh:property [
        sh:path time:hasDuration ;
        sh:maxCount 1 ;
        sh:nodeKind sh:BlankNodeOrIRI ;
        sh:class time:Duration
    ] .

# A duration carries its magnitude as a qudt Time-kind scalar rather than through
# time:numericDuration/time:unitType. Those cannot express a duration below the second:
# time:unitType ranges over time:TemporalUnit, whose smallest member is time:unitSecond,
# so a model written in milliseconds could only be recorded by rescaling it.

time:Duration
    a sh:NodeShape ;
    sh:targetClass time:Duration ;
    sh:message "A duration reads exactly one magnitude, in the temporal unit it was written in, and is never read against a clock." ;
    sh:node time:AuthoredDurationShape ;
    sh:property [
        sh:path time:numericDuration ;
        sh:maxCount 0
    ] ;
    sh:property [
        sh:path time:hasTRS ;
        sh:maxCount 0
    ] .

time:AuthoredDurationShape
    a sh:NodeShape ;
    sh:message "An authored duration needs a numeric magnitude and a temporal unit." ;
    sh:property [
        sh:path qudt:value ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:datatype xsd:double
    ] ;
    sh:property [
        sh:path qudt:unit ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:nodeKind sh:IRI
    ] ;
    sh:property [
        sh:path qudt:hasQuantityKind ;
        sh:minCount 1 ;
        sh:nodeKind sh:IRI ;
        sh:hasValue quantitykind:Time
    ] .
