diff --git a/src/component/event/events.ts b/src/component/event/events.ts index c3ce724..d02b6ec 100644 --- a/src/component/event/events.ts +++ b/src/component/event/events.ts @@ -1,6 +1,6 @@ import { Database } from "bun:sqlite"; import { TEventType, type TEvent } from "./event.types"; -import { getTsNow, pad_l2, transformArray } from "../../util"; +import { getTsNow, pad_l2, transformArray, formatTimeDiff, isEuropeanDST, subtractHours } from "../../util"; const BASE_URL = "https://77th-jsoc.com/service.php?action=get_events"; @@ -195,10 +195,13 @@ export class Event implements TEventEntity { return `${title_prefix_arr.length >= 1 ? ( title_prefix_arr.join(" " ) + " - ") : "" }${this.title} (${ TEventType[ this.event_type ] })`; } get_body() { + const BaseTime = new Date(`${this.date_at} 21:00`); + const RelativeEventTime = new Date(`${this.date_at} ${this.get_time_start()}`); + const TimeDiff = formatTimeDiff( BaseTime, RelativeEventTime); const body = [ `Title: ${this.title}`, `Date: ${this.date_at}`, - `Time: ${this.time_start}`, + `Time: ${this.get_time_start()}${ TimeDiff ? ` (Optime ${TimeDiff})` : "" }`, `Type: ${ TEventType[ this.event_type ] }`, `Location: ${this.location}`, `By: ${this.posted_by}`, @@ -219,4 +222,15 @@ export class Event implements TEventEntity { } return false; } + + get_time_start () { + const date = new Date( `${this.date_at} ${this.time_start}` ); + if ( ! isEuropeanDST( date ) ) { + const newDate = subtractHours( date, 1); + const hours = newDate.getHours(); + const minutes = newDate.getMinutes(); + return `${pad_l2(hours)}:${pad_l2(minutes)}`; + } + return this.time_start; + } } \ No newline at end of file diff --git a/src/util.ts b/src/util.ts index c8ab635..fff08e5 100644 --- a/src/util.ts +++ b/src/util.ts @@ -41,4 +41,51 @@ export function getTsNow() { } export function unixToDate( unix_timestamp: number ) { return new Date(unix_timestamp * 1000) } -export function dateToUnix( date: Date ) { return Math.round( date.getTime()/1000 ) } \ No newline at end of file +export function dateToUnix( date: Date ) { return Math.round( date.getTime()/1000 ) } + +export function formatTimeDiff(dateA: Date, dateB: Date) { + // Difference in milliseconds + const diffMs = dateB.getTime() - dateA.getTime(); + + // Get sign (+ or -) + const sign = diffMs < 0 ? "-" : ""; + + // Convert to absolute minutes + const diffMinutes = Math.floor(Math.abs(diffMs) / 60000); + + // Split into hours and minutes + const hours = Math.floor(diffMinutes / 60); + const minutes = diffMinutes % 60; + + // Return formatted string + return `${sign}${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`; +} + +export function subtractHours(date: Date, hours: number) { + // Create a new Date so we don't mutate the original + return new Date(date.getTime() - hours * 60 * 60 * 1000); +} + +// Helper: get last Sunday of a given month +function lastSundayOfMonth(year: number, month: number ) { + const lastDay = new Date(Date.UTC(year, month + 1, 0)); // last day of month + const day = lastDay.getUTCDay(); // 0 = Sunday + const diff = day === 0 ? 0 : day; // how far back to go to reach Sunday + lastDay.setUTCDate(lastDay.getUTCDate() - diff); + return lastDay; +} + +export function isEuropeanDST( date: Date ) { + const year = date.getFullYear(); + + // DST starts: last Sunday in March, 01:00 UTC + const start = lastSundayOfMonth(year, 2); // March (month = 2) + start.setUTCHours(1, 0, 0, 0); + + // DST ends: last Sunday in October, 01:00 UTC + const end = lastSundayOfMonth(year, 9); // October (month = 9) + end.setUTCHours(1, 0, 0, 0); + + // Return true if within DST period + return date >= start && date < end; +} \ No newline at end of file