diff --git a/src/util/util.js b/src/util/util.js index a4b4a71..bd6103a 100644 --- a/src/util/util.js +++ b/src/util/util.js @@ -19,8 +19,36 @@ exports.find = (buf, byte) => { return -1 } +// Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString#Polyfill +const timestampWithOffsetToISOString = (timestamp, offset) => { + const offsetHours = Math.floor(offset / 100) + const offsetMinutes = offset % 100 + + const pad = (number) => number < 10 ? '0' + number : number + + const date = new Date((timestamp + offsetHours * 3600 + offsetMinutes * 60) * 1000) + const dateString = date.getUTCFullYear() + + '-' + pad(date.getUTCMonth() + 1) + + '-' + pad(date.getUTCDate()) + + 'T' + pad(date.getUTCHours()) + + ':' + pad(date.getUTCMinutes()) + + ':' + pad(date.getUTCSeconds()) + + (offset >= 0 ? '+' : '-') + pad(offsetHours) + + ':' + pad(offsetMinutes) + return dateString +} + +// Last 6 characters will always be of the form ±hh:mm +const isoStringToTimestampWithOffset = (isoString) => { + const offset = isoString.slice(-6, -3) + isoString.slice(-2) + const offsetAsNumber = parseInt(offset) + const offsetInSeconds = Math.floor(offsetAsNumber / 100) * 3600 + (offsetAsNumber % 100) * 60 + + return Math.floor(new Date(isoString.slice(0, -6) + 'Z') / 1000) - offsetInSeconds + ' ' + offset +} + exports.parsePersonLine = (line) => { - let matched = line.match(/^(([^<]+)\s)?\s?<([^>]+)>\s?(\d+\s[+\-\d]+)?$/) + let matched = line.match(/^(([^<]+)\s)?\s?<([^>]+)>\s?(?:(\d+)\s([+-]\d+))?$/) if (matched === null) { return null } @@ -28,7 +56,7 @@ exports.parsePersonLine = (line) => { return { name: matched[2], email: matched[3], - date: matched[4] + date: matched[4] && matched[5] && timestampWithOffsetToISOString(parseInt(matched[4]), parseInt(matched[5])) } } @@ -39,7 +67,7 @@ exports.serializePersonLine = (node) => { } parts.push('<' + node.email + '>') if (node.date) { - parts.push(node.date) + parts.push(isoStringToTimestampWithOffset(node.date)) } return parts.join(' ') diff --git a/test/parse.spec.js b/test/parse.spec.js index aa7c6d0..163fe10 100644 --- a/test/parse.spec.js +++ b/test/parse.spec.js @@ -22,7 +22,7 @@ describe('utils', () => { expect(info).to.exist() expect(info.name).to.equal('Someone') expect(info.email).to.equal('some@one.somewhere') - expect(info.date).to.equal('123456 +0123') + expect(info.date).to.equal('1970-01-02T11:40:36+01:23') done() }) @@ -31,7 +31,7 @@ describe('utils', () => { expect(info).to.exist() expect(info.name).to.equal('So Me One') expect(info.email).to.equal('some@one.somewhere') - expect(info.date).to.equal('123456 +0123') + expect(info.date).to.equal('1970-01-02T11:40:36+01:23') done() }) @@ -40,7 +40,7 @@ describe('utils', () => { expect(info).to.exist() expect(info.name).to.not.exist() expect(info.email).to.equal('some@one.somewhere') - expect(info.date).to.equal('123456 +0123') + expect(info.date).to.equal('1970-01-02T11:40:36+01:23') done() }) @@ -49,7 +49,7 @@ describe('utils', () => { expect(info).to.exist() expect(info.name).to.not.exist() expect(info.email).to.equal('some@one.somewhere') - expect(info.date).to.equal('123456 +0123') + expect(info.date).to.equal('1970-01-02T11:40:36+01:23') done() }) @@ -58,7 +58,7 @@ describe('utils', () => { expect(info).to.exist() expect(info.name).to.equal('Some One & Other One') expect(info.email).to.equal('some@one.somewhere, other@one.elsewhere') - expect(info.date).to.equal('987654 +4321') + expect(info.date).to.equal('1970-01-14T05:41:54+43:21') done() }) diff --git a/test/resolver.spec.js b/test/resolver.spec.js index 66e409d..a076448 100644 --- a/test/resolver.spec.js +++ b/test/resolver.spec.js @@ -30,12 +30,12 @@ describe('IPLD format resolver (local)', () => { author: { name: 'John Doe', email: 'johndoe@example.com', - date: '1497302532 +0200' + date: '2017-06-12T23:22:12+02:00' }, committer: { name: 'John Doe', email: 'johndoe@example.com', - date: '1497302532 +0200' + date: '2017-06-12T23:22:12+02:00' }, encoding: 'ISO-8859-1', message: 'Encoded\n' @@ -49,7 +49,7 @@ describe('IPLD format resolver (local)', () => { tagger: { name: 'John Doe', email: 'johndoe@example.com', - date: '1497302532 +0200' + date: '2017-06-12T23:22:12+02:00' }, message: 'A message\n' } diff --git a/test/util.spec.js b/test/util.spec.js index a222167..759cdcb 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -18,7 +18,7 @@ describe('IPLD format util', () => { tagger: { name: 'John Doe', email: 'johndoe@example.com', - date: '1497302532 +0200' + date: '2017-06-12T23:22:12+02:00' }, message: 'A message\n' } @@ -29,7 +29,7 @@ describe('IPLD format util', () => { expect(Buffer.isBuffer(serialized)).to.equal(true) ipldGit.util.deserialize(serialized, (err, deserialized) => { expect(err).to.not.exist() - expect(tagNode).to.eql(deserialized) + expect(deserialized).to.eql(tagNode) done() }) })