PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | resources/js/lib/dateFormat.ts +62 -14 3.0.3 → 3.0.16 View file →
@@ -23,11 +23,14 @@
23 23 /**
24 24 * Get date format from Yatra settings
25 25 */
26 26 export function getDateFormat(): string {
27 + const w = window as any;
27 28 return (
28 - (window as any)?.yatraAdmin?.date_format ||
29 - (window as any)?.yatraAdmin?.dateFormat ||
29 + w?.yatraAdmin?.date_format ||
30 + w?.yatraAdmin?.dateFormat ||
31 + // Customer account pages localize their settings under yatraAccountPage.
32 + w?.yatraAccountPage?.date_format ||
30 33 "Y-m-d"
31 34 );
32 35 }
33 36
@@ -34,11 +37,13 @@
34 37 /**
35 38 * Get time format from Yatra settings
36 39 */
37 40 export function getTimeFormat(): string {
41 + const w = window as any;
38 42 return (
39 - (window as any)?.yatraAdmin?.time_format ||
40 - (window as any)?.yatraAdmin?.timeFormat ||
43 + w?.yatraAdmin?.time_format ||
44 + w?.yatraAdmin?.timeFormat ||
45 + w?.yatraAccountPage?.time_format ||
41 46 "H:i"
42 47 );
43 48 }
44 49
@@ -45,12 +50,45 @@
45 50 /**
46 51 * Get timezone from Yatra settings
47 52 */
48 53 export function getTimezone(): string {
49 - return (window as any)?.yatraAdmin?.timezone || "UTC";
54 + const w = window as any;
55 + return w?.yatraAdmin?.timezone || w?.yatraAccountPage?.timezone || "UTC";
50 56 }
51 57
52 58 /**
59 + * Parse a value into a Date, treating a date-only string ("YYYY-MM-DD") as a
60 + * LOCAL calendar date.
61 + *
62 + * `new Date("2026-08-01")` parses as UTC midnight, but the formatters read it
63 + * back with local getters (getDate/getMonth/…), so in any behind-UTC timezone
64 + * the day rolls back (Aug 1 → Jul 31) — e.g. a booking's travel_date showing
65 + * one day early. Building the Date from its parts pins it to the intended
66 + * calendar day regardless of timezone. Datetime strings (with a time part) and
67 + * Date objects are parsed/returned as before.
68 + */
69 +export function toDateValue(value: string | Date | null | undefined): Date {
70 + // Never hand back a non-Date. This previously returned `value` unchanged for
71 + // anything that wasn't a string, so a missing date came back as `undefined`
72 + // and the caller's `.toLocaleDateString()` threw — taking the whole admin
73 + // dashboard down with it via the error boundary. An Invalid Date keeps every
74 + // caller's date maths working (comparisons are simply false) and lets the
75 + // display helpers fall back to "-".
76 + if (value === null || value === undefined) return new Date(NaN);
77 + if (value instanceof Date) return value;
78 + if (typeof value !== "string") return new Date(NaN);
79 + const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim());
80 + if (dateOnly) {
81 + return new Date(
82 + Number(dateOnly[1]),
83 + Number(dateOnly[2]) - 1,
84 + Number(dateOnly[3]),
85 + );
86 + }
87 + return new Date(value);
88 +}
89 +
90 +/**
53 91 * Format a date string according to Yatra settings
54 92 * @param dateString - Date string in any parseable format (ISO, YYYY-MM-DD, etc.)
55 93 * @param includeTime - Whether to include time in the output
56 94 * @returns Formatted date string
@@ -61,10 +99,9 @@
61 99 ): string {
62 100 if (!dateString) return "-";
63 101
64 102 try {
65 - const date =
66 - typeof dateString === "string" ? new Date(dateString) : dateString;
103 + const date = toDateValue(dateString);
67 104
68 105 if (isNaN(date.getTime())) {
69 106 return String(dateString);
70 107 }
@@ -236,10 +273,9 @@
236 273 ): string {
237 274 if (!dateString) return "-";
238 275
239 276 try {
240 - const date =
241 - typeof dateString === "string" ? new Date(dateString) : dateString;
277 + const date = toDateValue(dateString);
242 278
243 279 if (isNaN(date.getTime())) {
244 280 // Try to parse as time only (HH:mm or HH:mm:ss)
245 281 if (
@@ -270,10 +306,9 @@
270 306 ): string {
271 307 if (!dateString) return "-";
272 308
273 309 try {
274 - const date =
275 - typeof dateString === "string" ? new Date(dateString) : dateString;
310 + const date = toDateValue(dateString);
276 311
277 312 if (isNaN(date.getTime())) {
278 313 return String(dateString);
279 314 }
@@ -312,9 +347,9 @@
312 347 export function parseDate(dateString: string | null | undefined): Date | null {
313 348 if (!dateString) return null;
314 349
315 350 try {
316 - const date = new Date(dateString);
351 + const date = toDateValue(dateString);
317 352 return isNaN(date.getTime()) ? null : date;
318 353 } catch (e) {
319 354 return null;
320 355 }
@@ -324,8 +359,22 @@
324 359 * Format date for input fields (always YYYY-MM-DD for HTML date inputs)
325 360 * @param dateString - Date string
326 361 * @returns Date in YYYY-MM-DD format for input fields
327 362 */
363 +/**
364 + * Today's date as a LOCAL "YYYY-MM-DD" string.
365 + *
366 + * Use this instead of `new Date().toISOString().split("T")[0]` for default/
367 + * "today" date values: toISOString() yields the UTC date, which is the wrong
368 + * calendar day for a user whose local date differs from UTC at that moment
369 + * (e.g. late evening in a behind-UTC zone, or early morning ahead of UTC) —
370 + * saving a payment/booking/rule date a day off. This reads the browser's local
371 + * calendar day.
372 + */
373 +export function todayYmd(): string {
374 + return formatDateForInput(new Date());
375 +}
376 +
328 377 export function formatDateForInput(
329 378 dateString: string | Date | null | undefined,
330 379 ): string {
331 380 if (!dateString) return "";
@@ -330,10 +379,9 @@
330 379 ): string {
331 380 if (!dateString) return "";
332 381
333 382 try {
334 - const date =
335 - typeof dateString === "string" ? new Date(dateString) : dateString;
383 + const date = toDateValue(dateString);
336 384
337 385 if (isNaN(date.getTime())) {
338 386 return "";
339 387 }