Skip to content

Commit

Permalink
Parse date into ISO 8601 format instead of seconds since UTC epoch
Browse files Browse the repository at this point in the history
Fix bwindels#14 by not converting to local or UTC date, instead slightly
modifying DateTime strings into easy-to-parse ISO 8601 format.

When a DateTime string follows the EXIF spec, we map some colons to
dashes to conform to ISO 8601.  The other supported format was
ISO 8601, so we don't do anything in this case.
  • Loading branch information
edemaine committed Jul 26, 2018
1 parent 1b08791 commit d8cd62e
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 77 deletions.
86 changes: 10 additions & 76 deletions lib/date.js
Original file line number Diff line number Diff line change
@@ -1,84 +1,18 @@
function parseNumber(s) {
return parseInt(s, 10);
}

//in seconds
var hours = 3600;
var minutes = 60;

//take date (year, month, day) and time (hour, minutes, seconds) digits in UTC
//and return a timestamp in seconds
function parseDateTimeParts(dateParts, timeParts) {
dateParts = dateParts.map(parseNumber);
timeParts = timeParts.map(parseNumber);
var year = dateParts[0];
var month = dateParts[1] - 1;
var day = dateParts[2];
var hours = timeParts[0];
var minutes = timeParts[1];
var seconds = timeParts[2];
var date = Date.UTC(year, month, day, hours, minutes, seconds, 0);
var timestamp = date / 1000;
return timestamp;
}

//parse date with "2004-09-04T23:39:06-08:00" format,
//one of the formats supported by ISO 8601, and
//convert to utc timestamp in seconds
function parseDateWithTimezoneFormat(dateTimeStr) {

var dateParts = dateTimeStr.substr(0, 10).split('-');
var timeParts = dateTimeStr.substr(11, 8).split(':');
var timezoneStr = dateTimeStr.substr(19, 6);
var timezoneParts = timezoneStr.split(':').map(parseNumber);
var timezoneOffset = (timezoneParts[0] * hours) +
(timezoneParts[1] * minutes);

var timestamp = parseDateTimeParts(dateParts, timeParts);
//minus because the timezoneOffset describes
//how much the described time is ahead of UTC
timestamp -= timezoneOffset;

if(typeof timestamp === 'number' && !isNaN(timestamp)) {
return timestamp;
}
}

//parse date with "YYYY:MM:DD hh:mm:ss" format, convert to utc timestamp in seconds
function parseDateWithSpecFormat(dateTimeStr) {
var parts = dateTimeStr.split(' '),
dateParts = parts[0].split(':'),
timeParts = parts[1].split(':');

var timestamp = parseDateTimeParts(dateParts, timeParts);

if(typeof timestamp === 'number' && !isNaN(timestamp)) {
return timestamp;
}
}

function parseExifDate(dateTimeStr) {
//some easy checks to determine two common date formats
//some easy checks to determine common date formats

//is the date in the standard "YYYY:MM:DD hh:mm:ss" format?
var isSpecFormat = dateTimeStr.length === 19 &&
dateTimeStr.charAt(4) === ':';
//is the date in the non-standard format,
//"2004-09-04T23:39:06-08:00" to include a timezone?
var isTimezoneFormat = dateTimeStr.length === 25 &&
dateTimeStr.charAt(10) === 'T';
var timestamp;

if(isTimezoneFormat) {
return parseDateWithTimezoneFormat(dateTimeStr);
}
else if(isSpecFormat) {
return parseDateWithSpecFormat(dateTimeStr);
}
//if so, convert to ISO 8601 by replacing first two ':'s with '-'s
if (dateTimeStr.length === 19 &&
dateTimeStr.charAt(4) === ':' &&
dateTimeStr.charAt(7) === ':') {
dateTimeStr = dateTimeStr.slice(0, 4) + '-' +
dateTimeStr.slice(5, 7) + '-' + dateTimeStr.slice(8);
}

return dateTimeStr;
}

module.exports = {
parseDateWithSpecFormat: parseDateWithSpecFormat,
parseDateWithTimezoneFormat: parseDateWithTimezoneFormat,
parseExifDate: parseExifDate
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"devDependencies": {
"browserify": "^7.0.0",
"uglify-js": "^2.4.15"
"uglify-js": "^2.4.15",
"nodeunit": "^0.11.3"
}
}

0 comments on commit d8cd62e

Please sign in to comment.