commit 9233fe93199b2a4c6a81029db07778ac92ecd881
parent 7750f9cb6df31717dfec5b0419911f9f514ce850
Author: Katja (ctucx) <git@ctu.cx>
Date: Wed, 16 Apr 2025 23:09:48 +0200
parent 7750f9cb6df31717dfec5b0419911f9f514ce850
Author: Katja (ctucx) <git@ctu.cx>
Date: Wed, 16 Apr 2025 23:09:48 +0200
use CustomDate class for date/time formating
7 files changed, 82 insertions(+), 108 deletions(-)
diff --git a/src/app_functions.js b/src/app_functions.js @@ -1,8 +1,51 @@ import { db } from './dataStorage.js'; import { settingsState } from './settings.js'; -import { generateSlug, loyaltyCardToString, loyaltyCardFromString } from './helpers.js'; import { getHafasClient, client } from './hafasClient.js'; import { trainsearchToHafas, hafasToTrainsearch } from './refresh_token/index.js'; +import { CustomDate } from './helpers.js'; + +const loyaltyCards = { + NONE: Symbol('no loyalty card'), + BAHNCARD: Symbol('Bahncard'), + VORTEILSCARD: Symbol('VorteilsCard'), + HALBTAXABO: Symbol('HalbtaxAbo'), + VOORDEELURENABO: Symbol('Voordeelurenabo'), + SHCARD: Symbol('SH-Card'), + GENERALABONNEMENT: Symbol('General-Abonnement'), +}; + +const loyaltyCardsReverse = { + 'Symbol(no loyalty card)': 'NONE', + 'Symbol(Bahncard)': 'BAHNCARD', + 'Symbol(VorteilsCard)': 'VORTEILSCARD', + 'Symbol(HalbtaxAbo)': 'HALBTAXABO', + 'Symbol(Voordeelurenabo)': 'VOORDEELURENABO', + 'Symbol(SH-Card)': 'SHCARD', + 'Symbol(General-Abonnement)': 'GENERALABONNEMENT', +}; + +export const loyaltyCardToString = loyaltyCard => + loyaltyCardsReverse[loyaltyCard.type.toString()] !== 'NONE' ? + `${loyaltyCardsReverse[loyaltyCard.type.toString()]}-${loyaltyCard.discount}-${loyaltyCard.class}` + : 'NONE'; + + +export const loyaltyCardFromString = string => { + const splitedString = string.split('-'); + if (splitedString[0] === 'NONE') return { type: loyaltyCards[splitedString[0]] }; + return { type: loyaltyCards[splitedString[0]], discount: splitedString[1], class: splitedString[2] }; +}; + +export const generateSlug = () => { + const len = 8; + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + for (let i = 0; i < len; i++) + result += characters.charAt(Math.floor(Math.random() * characters.length)); + + return result; +}; const journeySettings = () => { let params = { @@ -27,12 +70,12 @@ export const processLeg = leg => { const elements = [ 'plannedDeparture', 'plannedArrival', 'plannedWhen', 'departure', 'arrival', 'when' ]; elements.forEach(element => { - if (leg[element]) leg[element] = new Date(leg[element]); + if (leg[element]) leg[element] = new CustomDate(leg[element]); }); if (leg.stopovers) leg.stopovers.forEach(stopover => { elements.forEach(element => { - if (stopover[element]) stopover[element] = new Date(stopover[element]); + if (stopover[element]) stopover[element] = new CustomDate(stopover[element]); }); }); };
diff --git a/src/formatters.js b/src/formatters.js @@ -24,9 +24,6 @@ export const formatPoint = point => { }; }; -export const formatDate = date => `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`; -export const formatTime = date => `${padZeros(date.getHours())}:${padZeros(date.getMinutes())}`; - export const formatDuration = duration => { const mins = duration / 60000; const h = Math.floor(mins / 60);
diff --git a/src/helpers.js b/src/helpers.js @@ -1,72 +1,32 @@ -const loyaltyCards = { - NONE: Symbol('no loyalty card'), - BAHNCARD: Symbol('Bahncard'), - VORTEILSCARD: Symbol('VorteilsCard'), - HALBTAXABO: Symbol('HalbtaxAbo'), - VOORDEELURENABO: Symbol('Voordeelurenabo'), - SHCARD: Symbol('SH-Card'), - GENERALABONNEMENT: Symbol('General-Abonnement'), -}; - -const loyaltyCardsReverse = { - 'Symbol(no loyalty card)': 'NONE', - 'Symbol(Bahncard)': 'BAHNCARD', - 'Symbol(VorteilsCard)': 'VORTEILSCARD', - 'Symbol(HalbtaxAbo)': 'HALBTAXABO', - 'Symbol(Voordeelurenabo)': 'VOORDEELURENABO', - 'Symbol(SH-Card)': 'SHCARD', - 'Symbol(General-Abonnement)': 'GENERALABONNEMENT', -}; - export const sleep = delay => new Promise((resolve) => setTimeout(resolve, delay)); export const isEmptyObject = obj => Object.keys(obj).length === 0; export const padZeros = str => (('00' + str).slice(-2)); -export const ElementById = id => document.getElementById(id); - -export const showElement = element => element.classList.remove('hidden'); -export const hideElement = element => element.classList.add('hidden'); -export const elementHidden = element => element.classList.contains('hidden'); - -export const unflipElement = element => element.classList.remove('flipped'); -export const flipElement = element => element.classList.add('flipped'); export const setThemeColor = color => document.querySelector('meta[name="theme-color"]').setAttribute('content', color); export const queryBackgroundColor = (target, query) => window.getComputedStyle(target.querySelector(query)).getPropertyValue('background-color'); -export const isValidDate = date => { - const matches = /^(\d{4})[-\/](\d{2})[-\/](\d{2})$/.exec(date); - if (matches == null) { - return false; - } - - const d = matches[3]; - const m = matches[2]-1; - const y = matches[1]; - const composedDate = new Date(y, m, d); - return composedDate.getDate() == d && - composedDate.getMonth() == m && - composedDate.getFullYear() == y; -}; +export class CustomDate extends Date { + formatDate() { return `${this.getDate()}.${this.getMonth() + 1}.${this.getFullYear()}`; } + formatISODate() { return `${this.getFullYear()}-${padZeros(this.getMonth()+1)}-${padZeros(this.getDate())}`; } + formatISODateTime() { return `${this.formatISODate()}T${this.formatTime()}`; } + formatTime() { return `${padZeros(this.getHours())}:${padZeros(this.getMinutes())}`; } -export const loyaltyCardToString = loyaltyCard => - loyaltyCardsReverse[loyaltyCard.type.toString()] !== 'NONE' ? - `${loyaltyCardsReverse[loyaltyCard.type.toString()]}-${loyaltyCard.discount}-${loyaltyCard.class}` - : 'NONE'; - -export const loyaltyCardFromString = string => { - const splitedString = string.split('-'); - if (splitedString[0] === 'NONE') return { type: loyaltyCards[splitedString[0]] }; - return { type: loyaltyCards[splitedString[0]], discount: splitedString[1], class: splitedString[2] }; -}; - - -export const generateSlug = () => { - const len = 8; - let result = ''; - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + setDate(value) { + const splitValue = value.split('-'); + if (splitValue.length !== 3) return false; + this.setFullYear(splitValue[0], splitValue[1]-1, splitValue[2]); + } - for (let i = 0; i < len; i++) - result += characters.charAt(Math.floor(Math.random() * characters.length)); + setTime(value) { + const splitValue = value.split(':'); + if (splitValue.length !== 2) return false; + this.setHours(splitValue[0], splitValue[1]); + } - return result; -}; + setDateTime(value) { + const splitValue = value.split('T'); + if (splitValue.length !== 2) return false; + this.setDate(splitValue[0]); + this.setTime(splitValue[1]); + } +}
diff --git a/src/journeyView.js b/src/journeyView.js @@ -8,7 +8,7 @@ import { settings } from './settings.js'; import { t } from './languages.js'; import { getJourney, refreshJourney } from './app_functions.js'; import { remarksModal, platformTemplate, stopTemplate, timeTemplate } from './templates.js'; -import { formatPoint, formatDate, formatDuration, formatPrice, formatTrainTypes, formatLineAdditionalName, formatLineDisplayName } from './formatters.js'; +import { formatPoint, formatDuration, formatPrice, formatTrainTypes, formatLineAdditionalName, formatLineDisplayName } from './formatters.js'; import { cachedCoachSequence } from './coach-sequence/index.js'; import { baseStyles, helperStyles, flexboxStyles, headerStyles, iconStyles, cardStyles, journeyViewStyles } from './styles.js'; @@ -85,7 +85,7 @@ class JourneyView extends LitOverlay { <a class="icon-reload ${this.isUpdating ? 'spinning' : ''}" title="${t("reload")}" @click=${this.refreshJourney}></a> ${this.viewState !== null ? html` <h3>${formatPoint(this.viewState.legs[0].origin)} → ${formatPoint(this.viewState.legs[this.viewState.legs.length - 1].destination)}</h3> - <p><b>${t('duration')}: ${formatDuration(this.viewState.duration)} | ${t('changes')}: ${this.viewState.changes-1} | ${t('date')}: ${formatDate(this.viewState.legs[0].plannedDeparture)}${this.settingsState.showPrices && this.viewState.price ? html` | ${t('price')}: <td><span>${formatPrice(this.viewState.price)}</span></td>` : nothing}</b></p> + <p><b>${t('duration')}: ${formatDuration(this.viewState.duration)} | ${t('changes')}: ${this.viewState.changes-1} | ${t('date')}: ${this.viewState.legs[0].plannedDeparture.formatDate()}${this.settingsState.showPrices && this.viewState.price ? html` | ${t('price')}: <td><span>${formatPrice(this.viewState.price)}</span></td>` : nothing}</b></p> ` : html` <h3>... → ...</h3> <p><b>${t('duration')}: ... | ${t('changes')}: ... | ${t('date')}: ...</b></p>
diff --git a/src/journeysCanvas.js b/src/journeysCanvas.js @@ -1,8 +1,8 @@ import { LitElement, html, css } from 'lit'; import { LitOverlay } from './LitOverlay.js'; -import { sleep } from './helpers.js'; -import { formatTrainTypes, formatLineDisplayName, formatTime } from './formatters.js' +import { CustomDate, sleep } from './helpers.js'; +import { formatTrainTypes, formatLineDisplayName } from './formatters.js' import { cachedCoachSequence, coachSequenceCache, coachSequenceCacheKey } from './coach-sequence/index.js'; export class JourneysCanvas extends LitOverlay { @@ -328,9 +328,9 @@ export class JourneysCanvas extends LitOverlay { this.canvasContext.fillStyle = '#aaa'; while (time < this.canvasState.lastArrival) { const y = (time - this.canvasState.firstDeparture) * this.canvasState.scaleFactor + 32; - this.canvasContext.fillText(formatTime(time), (window.innerWidth / this.canvasState.dpr) > 600 ? 30 : 10, y); + this.canvasContext.fillText(time.formatTime(), (window.innerWidth / this.canvasState.dpr) > 600 ? 30 : 10, y); this.canvasContext.fillRect(0, y, this.canvasElement.width / this.canvasState.dpr, 1); - time = new Date(Number(time) + 3600000);//Math.floor(120/scaleFactor)); + time = new CustomDate(Number(time) + 3600000);//Math.floor(120/scaleFactor)); } this.canvasContext.fillStyle = '#fa5'; @@ -421,7 +421,7 @@ export class JourneysCanvas extends LitOverlay { if (journey.legs.indexOf(leg) == journey.legs.length - 1) times.push([leg.departure || leg.plannedDeparture, y - 9.5]); if (journey.legs.indexOf(leg) == 0) times.push([leg.arrival || leg.plannedArrival, y + duration + 7.5]); times.forEach(([time, y]) => { - preRenderedText = this.getTextCache(formatTime(time), '#fff', 15); + preRenderedText = this.getTextCache(time.formatTime(), '#fff', 15); this.canvasContext.scale(1 / this.canvasState.dpr, 1 / this.canvasState.dpr); this.canvasContext.drawImage(preRenderedText, Math.ceil(this.canvasState.dpr * (x + ((this.canvasState.rectWidth - preRenderedText.width/this.canvasState.dpr)) / 2)), this.canvasState.dpr * (y - 7.5)); this.canvasContext.scale(this.canvasState.dpr, this.canvasState.dpr);
diff --git a/src/searchView.js b/src/searchView.js @@ -7,7 +7,7 @@ import { client } from './hafasClient.js'; import { getIBNRbyDS100 } from './ds100.js'; import { formatPoint } from './formatters.js'; import { newJourneys } from './app_functions.js'; -import { padZeros, sleep, queryBackgroundColor, setThemeColor } from './helpers.js'; +import { CustomDate, padZeros, sleep, queryBackgroundColor, setThemeColor } from './helpers.js'; import { baseStyles, helperStyles, flexboxStyles, buttonInputStyles, iconStyles, searchViewStyles } from './styles.js'; import { settings } from './settings.js'; @@ -158,10 +158,10 @@ class SearchView extends LitOverlay { <div class="button now" title="${t('titleSetDateTimeNow')}" @click=${this.resetDate}>${t('now')}</div> ${!this.settingsState.combineDateTime ? html` <input type="time" name="time" title="${t('time')}" class="flex-grow" @change=${this.changeHandler} .value=${this.date.formatTime()} required> - <input type="date" name="date" title="${t('date')}" class="flex-grow" @change=${this.changeHandler} .value=${this.date.formatDate()} required> + <input type="date" name="date" title="${t('date')}" class="flex-grow" @change=${this.changeHandler} .value=${this.date.formatISODate()} required> ` : html` <input type="datetime-local" name="dateTime" title="${t('date')} & ${t('time')}" class="flex-grow" - @change=${this.changeHandler} .value=${this.date.formatDateTime()} required> + @change=${this.changeHandler} .value=${this.date.formatISODateTime()} required> `} </div> @@ -532,29 +532,4 @@ class SearchView extends LitOverlay { } } -class CustomDate extends Date { - formatDate() { return `${this.getFullYear()}-${padZeros(this.getMonth()+1)}-${padZeros(this.getDate())}`; } - formatTime() { return `${padZeros(this.getHours())}:${padZeros(this.getMinutes())}`; } - formatDateTime() { return `${this.formatDate()}T${this.formatTime()}`; } - - setDate(value) { - const splitValue = value.split('-'); - if (splitValue.length !== 3) return false; - this.setFullYear(splitValue[0], splitValue[1]-1, splitValue[2]); - } - - setTime(value) { - const splitValue = value.split(':'); - if (splitValue.length !== 2) return false; - this.setHours(splitValue[0], splitValue[1]); - } - - setDateTime(value) { - const splitValue = value.split('T'); - if (splitValue.length !== 2) return false; - this.setDate(splitValue[0]); - this.setTime(splitValue[1]); - } -} - customElements.define('search-view', SearchView);
diff --git a/src/templates.js b/src/templates.js @@ -1,10 +1,9 @@ import { html, css, nothing } from 'lit'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; -import { formatTime } from './formatters.js'; import { settingsState } from './settings.js'; import { getDS100byIBNR } from './ds100.js'; - +import { CustomDate } from './helpers.js'; export const remarksModal = (element, remarks) => element.showDialogOverlay('remarks', [].concat( remarks.map(remark => html` @@ -88,10 +87,10 @@ export const timeTemplate = (data, mode) => { const dateObj = getField('when') || getField('plannedWhen'); if (!dateObj) return '-'; - if (dateObj.toLocaleDateString() !== new Date().toLocaleDateString()) { - timeStr = `${formatTime(dateObj)}, ${dateObj.getDate()}.${dateObj.getMonth() + 1}.`; + if (dateObj.toLocaleDateString() !== new CustomDate().toLocaleDateString()) { + timeStr = `${dateObj.formatTime()}, ${dateObj.getDate()}.${dateObj.getMonth() + 1}.`; } else { - timeStr = formatTime(dateObj); + timeStr = dateObj.formatTime(); } const delayMinutes = Math.round(getField('delay') / 60);