UNPKG

@megaorm/zone

Version:

This package is designed to convert UTC datetimes to a specific timezone and helps format and display them as you like.

142 lines 5.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Zone = exports.ZoneError = void 0; const test_1 = require("@megaorm/test"); /** * Formats a Date object as a string in the format `YYYY-MM-DD hh:mm:ss`. * * @param date The Date object to format. * @returns A string representing the date in the format `YYYY-MM-DD hh:mm:ss`. */ function formatDate(date) { return date.toISOString().slice(0, 19).replace('T', ' '); } /** * Custom error class for handling errors specific to the Zone class. */ class ZoneError extends Error { } exports.ZoneError = ZoneError; /** * Represents a date and time in a specific timezone, providing utilities * for formatting and calculating time differences. */ class Zone { /** * Creates a new Zone instance based on a datetime and timezone. * * @param datetime The datetime string in `YYYY-MM-DD hh:mm:ss` fromat. * @param timezone The timezone identifier (e.g., `America/New_York`). * @throws `ZoneError` if the datetime or timezone is invalid. */ constructor(datetime, timezone) { if (!(0, test_1.isDateTime)(datetime)) { throw new ZoneError(`Invalid datetime: ${String(datetime)}`); } if (!(0, test_1.isFullStr)(timezone)) { throw new ZoneError(`Invalid timezone: ${String(timezone)}`); } try { // Create a UTC date object const utcDate = new Date(datetime.concat('Z')); // The datetime is assumed to be in UTC // Format the datetime in the specified timezone const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, // 24-hour format timeZone: timezone, }); // Get the local date in the target timezone const parts = formatter.formatToParts(utcDate); this.year = Number(parts.find((part) => part.type === 'year').value); this.month = Number(parts.find((part) => part.type === 'month').value); this.day = Number(parts.find((part) => part.type === 'day').value); this.hour = Number(parts.find((part) => part.type === 'hour').value); this.minute = Number(parts.find((part) => part.type === 'minute').value); this.second = Number(parts.find((part) => part.type === 'second').value); this.datetime = formatDate(new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second))); this.date = utcDate; this.timezone = timezone; } catch (error) { throw new ZoneError(error.message); } } /** * Formats the datetime using a custom formatter function. * * @param formatter A function that formats datetime components into a string. * @returns The formatted date-time string or the default datetime string. */ format(formatter) { if (!(0, test_1.isFunc)(formatter)) return this.datetime; const result = formatter(this.year, this.month, this.day, this.hour, this.minute, this.second); return (0, test_1.isStr)(result) ? result : this.datetime; } /** * Returns the date as a `YYYY-MM-DD` formatted string. * * @returns The date string. */ toDateString() { return `${this.year}-${String(this.month).padStart(2, '0')}-${String(this.day).padStart(2, '0')}`; } /** * Returns the time as a `hh:mm:ss` formatted string. * * @returns The time string. */ toTimestring() { return `${String(this.hour).padStart(2, '0')}:${String(this.minute).padStart(2, '0')}:${String(this.second).padStart(2, '0')}`; } /** * Returns the time in 12-hour AM/PM format. * * @returns The formatted time (e.g., `1:30 PM`). */ ampm() { let hour = this.hour % 12 || 12; // Converts 0 (midnight) to 12. const ampm = this.hour < 12 || this.hour === 24 ? 'AM' : 'PM'; return `${hour}:${String(this.minute).padStart(2, '0')} ${ampm}`; } /** * Calculates the time difference between now and the Zone's date. * * @returns A human-readable description of the time difference (e.g., `5 minutes ago`). */ diff() { const now = new Date(); const diff = now.getTime() - this.date.getTime(); if (diff < 0) return 'Just now'; // Case where the date is in the future const seconds = Math.floor(diff / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); const years = Math.floor(days / 365); let months = Math.floor(now.getMonth() - this.date.getMonth()); // If the current day is earlier than the target day, subtract 1 month if (now.getDate() < this.date.getDate()) months--; if (years > 0) return `${years} year${years > 1 ? 's' : ''} ago`; if (months > 0) return `${months} month${months > 1 ? 's' : ''} ago`; if (days > 0) return `${days} day${days > 1 ? 's' : ''} ago`; if (hours > 0) return `${hours} hour${hours > 1 ? 's' : ''} ago`; if (minutes > 0) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`; if (seconds > 0) return `${seconds} second${seconds > 1 ? 's' : ''} ago`; return 'Just now'; // Fallback when the time difference is too small } } exports.Zone = Zone; //# sourceMappingURL=index.js.map