/**
* bluebox.js - A webcomponent to display timelines
*
* Copyright (c) 2019, Luis Panadero Guardeño <luis.panadero(at)gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* Pseudo enum that represent a Time Unit stored on a Number
* @readonly
*/
class TimeUnit {
#name;
#intlDateTimeFormat;
/**
* Creates a new TimeUnit
* @param {string} name - Name
* @param {Object} intlDateTimeFormat - Intl.DateTimeFormat format options object
*/
constructor(name, intlDateTimeFormat) {
this.#name = name;
this.#intlDateTimeFormat = intlDateTimeFormat;
Object.freeze(this);
}
static Millisecond = new TimeUnit('millisecond', {timeStyle: "short"} );
static Second = new TimeUnit('second', {timeStyle: "short"});
static Minute = new TimeUnit('minute', {timeStyle: "short"});
static Hour = new TimeUnit('hour', {timeStyle: "short"});
static Day = new TimeUnit('day', {dateStyle: "short"});
static Year = new TimeUnit('year', {year: "numeric", 'era': "short"});
/**
* Gets a TimeUnit from a string value
* @param {string} value - String name of a TimeUnit
* @return {TimeUnit} A TimeUnit instance or null
*/
static fromName(value) {
for (let timeUnit of [TimeUnit.Millisecond, TimeUnit.Second, TimeUnit.Minute, TimeUnit.Hour, TimeUnit.Day, TimeUnit.Year]) {
if (timeUnit.#name === value) {
return timeUnit;
}
}
return null;
}
/**
* Convert a date to a Number using the time unit
* @param {Date} date - Input Date
* @return {number} - A number, that using this TimeUnit, represents the same Date
*/
convertFromDate(date) {
if (this == TimeUnit.Millisecond) {
return date.getTime();
} else if (this == TimeUnit.Second) {
return date.getTime() / 1000;
} else if (this == TimeUnit.Minute) {
return (date.getTime() / 1000) / 60;
} else if (this == TimeUnit.Hour) {
return (date.getTime() / 1000) / 3600;
} else if (this == TimeUnit.Day) {
return (date.getTime() / 1000) / 3600 / 24;
} else if (this == TimeUnit.Year) {
return date.getUTCFullYear();
}
return date.getTime();
}
/**
* Convert a date to a Number using the time unit
* @param {number} value - Input value in TimeUnits
* @return {Date} - A equivalent Date to the value in TimeUnits.
*/
convertToDate(value) {
if (this == TimeUnit.Millisecond) {
return new Date(value);
} else if (this == TimeUnit.Second) {
return new Date(value * 1000);
} else if (this == TimeUnit.Minute) {
return new Date(value * 1000 * 60);
} else if (this == TimeUnit.Hour) {
return new Date(value * 1000 * 3600);
} else if (this == TimeUnit.Day) {
return new Date(value * 1000 * 3600 * 24);
} else if (this == TimeUnit.Year) {
const date = new Date(Date.UTC(value, 0, 0));
// Hack to handle correctly yers between 0 and 999
date.setUTCFullYear(value);
return date;
}
return new Date(value);
}
/**
* Returns a functions that formats a value in TimeUnits to a String representation
* @param {string} locale - String locale conden
* @param {Object} [formatOptions] - Intl.DateTimeFormat format options object
* @return {Function(zoomFactor, value)} A format function for the TimeUnit values
*/
defaultFormatFunction(locale, formatOptions) {
const timeUnit = this;
const defaultIntlFormatFunction = new Intl.DateTimeFormat(locale, formatOptions || this.#intlDateTimeFormat).format;
return function(zoomFactor, value) { return defaultIntlFormatFunction(timeUnit.convertToDate(value))};
}
/**
* @return {string} String representation of a TimeUnit for debuing porpuses
*/
toString() {
return `TimeUnit.${this.#name}`;
}
/**
* Name of a TimeUnit. Aka, his string value representation
*/
get name () {
return this.#name;
}
}
export default TimeUnit;