Skip to content

Commit

Permalink
add claims: support month and day precisions
Browse files Browse the repository at this point in the history
  • Loading branch information
maxlath committed Oct 30, 2017
1 parent 983d3a9 commit 94c13f0
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
4 changes: 3 additions & 1 deletion docs/how_to.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,10 @@ Special cases:
// Monolingualtext property
wdEdit.claim.add('Q4115189', 'P1476', [ 'bulgroz', 'it' ])

// Time property: only year precision is supported yet (PR welcome!)
// Time property: only year, month, and day precision are supported yet (PR welcome!)
wdEdit.claim.add('Q4115189', 'P569', '1802')
wdEdit.claim.add('Q4115189', 'P569', '1802-02')
wdEdit.claim.add('Q4115189', 'P569', '1802-02-26')

// Quantity:
// pass a single value for a count without a specific unit
Expand Down
16 changes: 3 additions & 13 deletions lib/claim/builders.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const wdk = require('wikidata-sdk')
const getTimeObject = require('./get_time_object')

// The difference in builders are due to the different expectations of Wikidata API

Expand All @@ -8,7 +9,7 @@ const singleClaimBuilders = {
const id = wdk.getNumericId(Q)
return `{"entity-type":"item","numeric-id":${id}}`
},
time: year => JSON.stringify(getYearTimeObject(year)),
time: time => JSON.stringify(getTimeObject(time)),
// Property type specific builders
monolingualtext: valueArray => {
const [ text, language ] = valueArray
Expand All @@ -35,7 +36,7 @@ const entityEditBuilders = {
monolingualtext: (pid, valueObj) => {
return statementBase(pid, 'monolingualtext', valueObj)
},
time: (pid, year) => statementBase(pid, 'time', getYearTimeObject(year)),
time: (pid, time) => statementBase(pid, 'time', getTimeObject(time)),
quantity: (pid, num) => {
return statementBase(pid, 'quantity', {
lowerBound: `+${num}`,
Expand All @@ -51,17 +52,6 @@ const buildAmount = num => {
return num > 0 ? `+${num}` : `-${num}`
}

const getYearTimeObject = year => {
return {
time: `+${year}-00-00T00:00:00Z`,
timezone: 0,
before: 0,
after: 0,
precision: 9,
calendarmodel: 'http://www.wikidata.org/entity/Q1985727'
}
}

const statementBase = (pid, type, value) => {
return {
rank: 'normal',
Expand Down
31 changes: 31 additions & 0 deletions lib/claim/get_time_object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module.exports = time => {
const precision = getPrecisionIndex(time)
return timePrecisionObjectBuilders[precision](time)
}

const timePrecisions = [ 'year', 'month', 'day' ]

const getPrecisionIndex = time => timePrecisions[time.split('-').length - 1]

const timePrecisionObjectBuilders = {
year: year => getPrecisionTimeObject(9, `${year}-00-00${isoTimeRest}`),
month: month => getPrecisionTimeObject(10, `${month}-00${isoTimeRest}`),
day: day => getPrecisionTimeObject(11, `${day}${isoTimeRest}`)
}

const getPrecisionTimeObject = (precision, time) => {
const sign = time[0]
// The Wikidata API expects signed years
// Default to a positive year sign
if (sign !== '-' || sign !== '+') time = `+${time}`
return {
time,
timezone: 0,
before: 0,
after: 0,
precision,
calendarmodel: 'http://www.wikidata.org/entity/Q1985727'
}
}

const isoTimeRest = 'T00:00:00Z'
13 changes: 12 additions & 1 deletion lib/datatype_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ const _ = require('./utils')
module.exports = {
string: _.isNonEmptyString,
claim: wdk.isEntityId,
time: year => /^\d{4}$/.test(year.toString()),
// See https://www.mediawiki.org/wiki/Wikibase/DataModel#Dates_and_times
// The positive years will be signed later
time: time => {
// Parsing as an ISO String should not throw an Invalid time value error
try {
(new Date(time)).toISOString()
} catch (err) {
return false
}
// Only precision up to the day is handled
return /^(-|\+)?\d{1,16}(-\d{2}){0,2}$/.test(time.toString())
},
monolingualtext: value => {
const [ text, language ] = value
return _.isNonEmptyString(text) && _.isNonEmptyString(language)
Expand Down
29 changes: 29 additions & 0 deletions test/claim/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,35 @@ describe('claim add', () => {
.catch(done)
})

it('should add a claim with a month', function (done) {
this.timeout(20 * 1000)
checkAndAddClaim(sandboxEntity, 'P569', '1802-02')
.then(res => {
res.success.should.equal(1)
done()
})
.catch(done)
})

it('should add a claim with a day', function (done) {
this.timeout(20 * 1000)
checkAndAddClaim(sandboxEntity, 'P569', '1802-02-03')
.then(res => {
res.success.should.equal(1)
done()
})
.catch(done)
})

it('should reject a claim with an invalid time', function (done) {
this.timeout(20 * 1000)
checkAndAddClaim(sandboxEntity, 'P569', '1802-22-33')
.catch(err => {
err.message.should.equal('invalid time value')
done()
})
})

it('should add a claim with monolingualtext', function (done) {
this.timeout(20 * 1000)
checkAndAddClaim(sandboxEntity, 'P1476', [ 'bulgroz', 'fr' ])
Expand Down

0 comments on commit 94c13f0

Please sign in to comment.