112 lines
3.7 KiB
JavaScript
112 lines
3.7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.ExifDate = void 0;
|
|
const luxon_1 = require("luxon");
|
|
const DateTime_1 = require("./DateTime");
|
|
const Maybe_1 = require("./Maybe");
|
|
const String_1 = require("./String");
|
|
const StrictExifRE = /^\d{1,4}:\d{1,2}:\d{1,2}|\d{1,4}-\d{1,2}-\d{1,2}$/;
|
|
const LooseExifRE = /^\S+\s+\S+\s+\S+$/;
|
|
/**
|
|
* Encodes an ExifDate
|
|
*/
|
|
class ExifDate {
|
|
year;
|
|
month;
|
|
day;
|
|
rawValue;
|
|
static from(exifOrIso) {
|
|
return (
|
|
// in order of strictness:
|
|
this.fromExifStrict(exifOrIso) ??
|
|
this.fromISO(exifOrIso) ??
|
|
this.fromExifLoose(exifOrIso));
|
|
}
|
|
static fromISO(text) {
|
|
return StrictExifRE.test((0, String_1.toS)(text).trim())
|
|
? this.fromDateTime(luxon_1.DateTime.fromISO(text), text)
|
|
: undefined;
|
|
}
|
|
static fromPatterns(text, fmts) {
|
|
if ((0, String_1.blank)(text))
|
|
return;
|
|
text = (0, String_1.toS)(text).trim();
|
|
for (const fmt of fmts) {
|
|
const dt = luxon_1.DateTime.fromFormat(text, fmt);
|
|
if ((0, DateTime_1.validDateTime)(dt)) {
|
|
return this.fromDateTime(dt, text);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
// These are all formats I've seen in the wild from exiftool's output.
|
|
// More iterations might make sense, like "d MMM, y" or "MMM d, y", but I
|
|
// want to be constrained in what I consider a valid date to lessen the
|
|
// chance of misinterpreting a given value.
|
|
static fromExifStrict(text) {
|
|
return StrictExifRE.test((0, String_1.toS)(text).trim())
|
|
? this.fromPatterns(text, ["y:MM:dd", "y-MM-dd", "y:M:d"])
|
|
: undefined;
|
|
}
|
|
static fromExifLoose(text) {
|
|
// Unfortunately, Luxon parses "00" and "01" as _today_. So if we don't
|
|
// three non-blank strings parts, reject.
|
|
return LooseExifRE.test((0, String_1.toS)(text).trim())
|
|
? this.fromPatterns(text, ["MMM d y", "MMMM d y"])
|
|
: undefined;
|
|
}
|
|
static fromEXIF(text) {
|
|
return (0, Maybe_1.firstDefinedThunk)([
|
|
() => this.fromExifStrict(text),
|
|
() => this.fromExifLoose(text),
|
|
]);
|
|
}
|
|
static fromDateTime(dt, rawValue) {
|
|
return (0, DateTime_1.validDateTime)(dt)
|
|
? new ExifDate(dt.year, dt.month, dt.day, rawValue)
|
|
: undefined;
|
|
}
|
|
constructor(year, // full year (probably 2019-ish, but maybe Japanese 30-ish). See https://ericasadun.com/2018/12/25/iso-8601-yyyy-yyyy-and-why-your-year-may-be-wrong/
|
|
month, // 1-12, (no crazy 0-11 nonsense from Date!)
|
|
day, // 1-31
|
|
rawValue) {
|
|
this.year = year;
|
|
this.month = month;
|
|
this.day = day;
|
|
this.rawValue = rawValue;
|
|
}
|
|
toDate() {
|
|
return new Date(this.year, this.month - 1, this.day);
|
|
}
|
|
/**
|
|
* @param deltaMs defaults to 12 hours, so toMillis() is in the middle of the day.
|
|
*
|
|
* @return the epoch milliseconds for this day in UTC, plus `deltaMs` milliseconds.
|
|
*/
|
|
toMillis(deltaMs = 12 * DateTime_1.HourMs) {
|
|
return this.toDate().getTime() + deltaMs;
|
|
}
|
|
toISOString() {
|
|
return this.toString("-");
|
|
}
|
|
toExifString() {
|
|
return this.toString(":");
|
|
}
|
|
toString(sep = "-") {
|
|
return `${this.year}${sep}${(0, String_1.pad2)(this.month, this.day).join(sep)}`;
|
|
}
|
|
toJSON() {
|
|
return {
|
|
_ctor: "ExifDate",
|
|
year: this.year,
|
|
month: this.month,
|
|
day: this.day,
|
|
rawValue: this.rawValue,
|
|
};
|
|
}
|
|
static fromJSON(json) {
|
|
return new ExifDate(json.year, json.month, json.day, json.rawValue);
|
|
}
|
|
}
|
|
exports.ExifDate = ExifDate;
|
|
//# sourceMappingURL=ExifDate.js.map
|