/** * Some utils for manipulating dates * * **WARNING** experimental */ /** * Return the date to local ISO date, like YYYY-mm-dd * * The date is valid for the same timezone as the date's locale * * Do not take time into account * */ export const dateToISO = (date: Date | null): string | null => { if (null === date) { return null; } return [ date.getFullYear(), (date.getMonth() + 1).toString().padStart(2, "0"), date.getDate().toString().padStart(2, "0"), ].join("-"); }; /** * Return a date object from iso string formatted as YYYY-mm-dd * * **Experimental** */ export const ISOToDate = (str: string | null): Date | null => { if (null === str) { return null; } if ("" === str.trim()) { return null; } // If the string already contains time info, use it directly if (str.includes('T') || str.includes(' ')) { return new Date(str); } // Otherwise, parse date only const [year, month, day] = str.split("-").map((p) => parseInt(p)); return new Date(year, month - 1, day, 0, 0, 0, 0); }; /** * Return a date object from iso string formatted as YYYY-mm-dd:HH:MM:ss+01:00 * */ export const ISOToDatetime = (str: string | null): Date | null => { if (null === str) { return null; } const [cal, times] = str.split("T"), [year, month, date] = cal.split("-").map((s) => parseInt(s)), [time, timezone] = times.split(times.charAt(8)), [hours, minutes, seconds] = time.split(":").map((s) => parseInt(s)); if ("0000" === timezone) { return new Date( Date.UTC(year, month - 1, date, hours, minutes, seconds), ); } return new Date(year, month - 1, date, hours, minutes, seconds); }; /** * Convert a date to ISO8601, valid for usage in api * */ export const datetimeToISO = (date: Date): string => { let cal, time, offset; cal = [ date.getFullYear(), (date.getMonth() + 1).toString().padStart(2, "0"), date.getDate().toString().padStart(2, "0"), ].join("-"); time = [ date.getHours().toString().padStart(2, "0"), date.getMinutes().toString().padStart(2, "0"), date.getSeconds().toString().padStart(2, "0"), ].join(":"); offset = [ date.getTimezoneOffset() <= 0 ? "+" : "-", Math.abs(Math.floor(date.getTimezoneOffset() / 60)) .toString() .padStart(2, "0"), ":", Math.abs(date.getTimezoneOffset() % 60) .toString() .padStart(2, "0"), ].join(""); const x = cal + "T" + time + offset; return x; }; export const intervalDaysToISO = (days: number | string | null): string => { if (null === days) { return "P0D"; } return `P${days}D`; }; export const intervalISOToDays = (str: string | null): number | null => { if (null === str) { return null; } if ("" === str.trim()) { return null; } let days = 0; let isDate = true; let vstring = ""; for (let i = 0; i < str.length; i = i + 1) { if (!isDate) { continue; } switch (str.charAt(i)) { case "P": isDate = true; break; case "T": isDate = false; break; case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": vstring = vstring + str.charAt(i); break; case "Y": days = days + Number.parseInt(vstring) * 365; vstring = ""; break; case "M": days = days + Number.parseInt(vstring) * 30; vstring = ""; break; case "D": days = days + Number.parseInt(vstring); vstring = ""; break; default: throw Error( "this character should not appears: " + str.charAt(i), ); } } return days; };