mirror of https://github.com/ekimekim/wubloader
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import { DateTime } from "luxon";
|
|
|
|
export enum TimeType {
|
|
UTC,
|
|
BusTime,
|
|
TimeAgo,
|
|
}
|
|
|
|
export function dateTimeFromWubloaderTime(wubloaderTime: string): DateTime | null {
|
|
const dt = DateTime.fromISO(wubloaderTime, { zone: "UTC" });
|
|
if (dt.isValid) {
|
|
return dt;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function wubloaderTimeFromDateTime(dateTime: DateTime): string {
|
|
// Not using ISO here because Luxon doesn't give us a quick way to print an ISO8601 string with no offset.
|
|
return dateTime.toFormat("yyyy-LL-dd'T'HH:mm:ss.SSS");
|
|
}
|
|
|
|
class DateTimeMathObject {
|
|
hours: number;
|
|
minutes: number;
|
|
seconds: number;
|
|
}
|
|
|
|
function dateTimeMathObjectFromBusTime(busTime: string): DateTimeMathObject | null {
|
|
// We need to handle inputs like "-0:10:15" in a way that consistently makes the time negative.
|
|
// Since we can't assign the negative sign to any particular part, we'll check for the whole thing here.
|
|
let direction = 1;
|
|
if (busTime.startsWith("-")) {
|
|
busTime = busTime.slice(1);
|
|
direction = -1;
|
|
}
|
|
|
|
const parts = busTime.split(":", 3);
|
|
const hours = parseInt(parts[0], 10) * direction;
|
|
const minutes = parts.length > 1 ? parseInt(parts[1], 10) * direction : 0;
|
|
const seconds = parts.length > 2 ? parseInt(parts[2], 10) * direction : 0;
|
|
return { hours: hours, minutes: minutes, seconds: seconds };
|
|
}
|
|
|
|
export function dateTimeFromBusTime(busStartTime: DateTime, busTime: string): DateTime | null {
|
|
const busMathObject = dateTimeMathObjectFromBusTime(busTime);
|
|
if (busMathObject === null) {
|
|
return null;
|
|
}
|
|
return busStartTime.plus(busMathObject);
|
|
}
|
|
|
|
export function busTimeFromDateTime(busStartTime: DateTime, time: DateTime): string {
|
|
const diff = time.diff(busStartTime);
|
|
if (diff.milliseconds < 0) {
|
|
const negativeInterval = diff.negate();
|
|
return `-${negativeInterval.toFormat("hh:mm:ss.SSS")}`;
|
|
}
|
|
return diff.toFormat("hh:mm:ss.SSS");
|
|
}
|
|
|
|
export function dateTimeFromTimeAgo(timeAgo: string): DateTime | null {
|
|
const parts = timeAgo.split(":");
|
|
const properties = ["hours", "minutes", "seconds"];
|
|
const mathObj = {};
|
|
|
|
while (parts.length > 0) {
|
|
const nextPart = parts.pop();
|
|
if (properties.length === 0) {
|
|
return null;
|
|
}
|
|
const nextProp = properties.pop();
|
|
const partNumber = parseInt(nextPart, 10);
|
|
if (isNaN(partNumber)) {
|
|
return null;
|
|
}
|
|
mathObj[nextProp] = partNumber;
|
|
}
|
|
|
|
const now = DateTime.utc();
|
|
return now.plus(mathObj);
|
|
}
|
|
|
|
export function timeAgoFromDateTime(dateTime: DateTime): string {
|
|
const currentTime = DateTime.utc();
|
|
const interval = currentTime.diff(dateTime, "seconds");
|
|
let timeAgoSeconds = interval.seconds;
|
|
|
|
let negative = "";
|
|
if (timeAgoSeconds < 0) {
|
|
negative = "-";
|
|
timeAgoSeconds = -timeAgoSeconds;
|
|
}
|
|
|
|
const seconds = (((timeAgoSeconds % 60) * 1000) | 0) / 1000;
|
|
const secondsString = seconds < 10 ? `0${seconds}` : seconds.toString();
|
|
const minutes = (timeAgoSeconds / 60) % 60 | 0;
|
|
const minutesString = minutes < 10 ? `0${minutes}` : minutes.toString();
|
|
const hours = Math.floor(timeAgoSeconds / 3600);
|
|
|
|
return `${negative}${hours}:${minutesString}:${secondsString}`;
|
|
}
|