mirror of https://github.com/ekimekim/wubloader
Add the time converter utility
parent
ea438c73db
commit
1c842d9d16
@ -0,0 +1,96 @@
|
||||
import { l } from "vite/dist/node/types.d-aGj9QkWt";
|
||||
import { DateTime } from "../external/luxon.min";
|
||||
|
||||
export function dateTimeFromWubloaderTime(wubloaderTime: string): DateTime | null {
|
||||
const dt = DateTime.fromISO(wubloaderTime);
|
||||
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}`;
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
import { Accessor, Component, createSignal } from "solid-js";
|
||||
import { DateTime } from "../external/luxon.min";
|
||||
import {
|
||||
dateTimeFromWubloaderTime,
|
||||
dateTimeFromBusTime,
|
||||
dateTimeFromTimeAgo,
|
||||
wubloaderTimeFromDateTime,
|
||||
busTimeFromDateTime,
|
||||
timeAgoFromDateTime,
|
||||
} from "../common/convertTime";
|
||||
|
||||
interface TimeConverterProps {
|
||||
busStartTime: Accessor<DateTime | null>;
|
||||
}
|
||||
|
||||
enum TimeType {
|
||||
UTC,
|
||||
BusTime,
|
||||
TimeAgo,
|
||||
}
|
||||
|
||||
const TimeConverter: Component<TimeConverterProps> = (props) => {
|
||||
const [enteredTime, setEnteredTime] = createSignal<string>("");
|
||||
const [startTimeType, setStartTimeType] = createSignal<TimeType>(TimeType.UTC);
|
||||
const [outputTimeType, setOutputTimeType] = createSignal<TimeType>(TimeType.UTC);
|
||||
|
||||
const outputString = (): string => {
|
||||
const busStartTime = props.busStartTime();
|
||||
if (busStartTime === null) {
|
||||
return "";
|
||||
}
|
||||
const startType = startTimeType();
|
||||
let dateTime: DateTime | null = null;
|
||||
if (startType === TimeType.UTC) {
|
||||
dateTime = dateTimeFromWubloaderTime(enteredTime());
|
||||
} else if (startType === TimeType.BusTime) {
|
||||
dateTime = dateTimeFromBusTime(busStartTime, enteredTime());
|
||||
} else if (startType === TimeType.TimeAgo) {
|
||||
dateTime = dateTimeFromTimeAgo(enteredTime());
|
||||
}
|
||||
if (dateTime === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const outputType = outputTimeType();
|
||||
if (outputType === TimeType.UTC) {
|
||||
return wubloaderTimeFromDateTime(dateTime);
|
||||
}
|
||||
if (outputType === TimeType.BusTime) {
|
||||
return busTimeFromDateTime(busStartTime, dateTime);
|
||||
}
|
||||
if (outputType === TimeType.TimeAgo) {
|
||||
return timeAgoFromDateTime(dateTime);
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
return (
|
||||
<form>
|
||||
<h1>Convert Times</h1>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Time to convert"
|
||||
value={enteredTime()}
|
||||
onInput={(event) => {
|
||||
setEnteredTime(event.currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
From:
|
||||
<label>
|
||||
<input
|
||||
name="time-converter-from"
|
||||
type="radio"
|
||||
value={TimeType.UTC}
|
||||
checked={true}
|
||||
onClick={(event) => setStartTimeType(TimeType.UTC)}
|
||||
/>
|
||||
UTC
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="time-converter-from"
|
||||
type="radio"
|
||||
value={TimeType.BusTime}
|
||||
onClick={(event) => setStartTimeType(TimeType.BusTime)}
|
||||
/>
|
||||
Bus Time
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="time-converter-from"
|
||||
type="radio"
|
||||
value={TimeType.TimeAgo}
|
||||
onClick={(event) => setStartTimeType(TimeType.TimeAgo)}
|
||||
/>
|
||||
Time Ago
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
To:
|
||||
<label>
|
||||
<input
|
||||
name="time-converter-to"
|
||||
type="radio"
|
||||
checked={true}
|
||||
value={TimeType.UTC}
|
||||
onClick={(event) => setOutputTimeType(TimeType.UTC)}
|
||||
/>
|
||||
UTC
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="time-converter-to"
|
||||
type="radio"
|
||||
value={TimeType.BusTime}
|
||||
onClick={(event) => setOutputTimeType(TimeType.BusTime)}
|
||||
/>
|
||||
Bus Time
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="time-converter-to"
|
||||
type="radio"
|
||||
value={TimeType.TimeAgo}
|
||||
onClick={(event) => setOutputTimeType(TimeType.TimeAgo)}
|
||||
/>
|
||||
Time Ago
|
||||
</label>
|
||||
</div>
|
||||
<div>Converted Time: {outputString()}</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default TimeConverter;
|
Loading…
Reference in New Issue