UNPKG

phx-node

Version:

PHX NODE

301 lines 12.9 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PHXDateHelpers = void 0; const common_1 = require("@nestjs/common"); const constant_1 = require("../../lib/constant"); let PHXDateHelpers = class PHXDateHelpers { calculateDateDifference(startDate, endDate, valueReturnIfNotValidDate = 0) { if (!startDate || !endDate) return valueReturnIfNotValidDate; const getDateWithTime = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0).getTime(); const startDateWithTime = getDateWithTime(new Date(startDate)); const endDateWithTime = getDateWithTime(new Date(endDate)); if (startDateWithTime >= endDateWithTime) return valueReturnIfNotValidDate; const differenceInDays = (endDateWithTime - startDateWithTime) / (1000 * 60 * 60 * 24); return Math.round(differenceInDays); } dateStrToDate(date) { if (!date) return ""; return date.slice(8, 10) + "/" + date.slice(5, 7) + "/" + date.slice(0, 4); } dateStrToDateTime(date, isTimeFirst = true) { if (!date) return "---"; const time = date.slice(11, 16); const day = date.slice(8, 10); const month = date.slice(5, 7); const year = date.slice(0, 4); const dateStr = day + "/" + month + "/" + year; if (isTimeFirst) { return time + " " + dateStr; } else { return dateStr + " " + time; } } formatDateHyphen(timestamp) { if (!timestamp) return null; const date = new Date(timestamp); const day = date.getUTCDate(); const month = date.getUTCMonth() + 1; const year = date.getUTCFullYear(); const fullDay = day < 10 ? `0${day}` : day; const fullMonth = month < 10 ? `0${month}` : month; const formattedDate = `${year}-${fullMonth}-${fullDay}`; return formattedDate; } //hàm tính khoảng thời gian từ start - end calculateRemainingTime(startTimeString, endTimeString) { if (startTimeString && endTimeString) { const startTime = new Date(startTimeString); const endTime = new Date(endTimeString); const timeDifference = endTime - startTime; const timeDifferenceInSeconds = timeDifference / 1000; const hours = Math.floor(timeDifferenceInSeconds / 3600); const minutes = Math.floor((timeDifferenceInSeconds % 3600) / 60); const remainingSeconds = timeDifferenceInSeconds % 60; return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(Math.floor(remainingSeconds)).padStart(2, "0")}`; } } dateStrToTime(dateStr) { const date = new Date(dateStr); const hours = date.getHours(); const minutes = date.getMinutes(); return `${hours}:${minutes < 10 ? "0" : ""}${minutes}`; } //trả về true nếu thời gian truyền vào nhỏ hơn thời gian hiện tại isPastDate(compareDate) { const inputDate = new Date(compareDate); const today = new Date(); today.setHours(0, 0, 0, 0); return inputDate < today; } parseDateToParts(isoString, type = "string") { const date = new Date(isoString); const day = date.getDate(); const month = date.getMonth(); const year = date.getFullYear(); const hour = date.getHours(); const minute = date.getMinutes(); if (type === "number") { return { day, month, year, hour, minute }; } const pad = (n) => n.toString().padStart(2, "0"); const dayString = pad(day); const monthString = pad(month + 1); const yearString = year.toString(); const hourString = pad(hour); const minuteString = pad(minute); return { day: dayString, month: monthString, year: yearString, hour: hourString, minute: minuteString, time: `${hourString}:${minuteString}`, }; } unaccentValue(rawValue) { if (!rawValue) return ""; return rawValue .normalize("NFD") .replace(/[\u0300-\u036f]/g, "") .replace(/Đ/g, "D") .replace(/đ/g, "d"); } stringToDate(dateString) { if (!dateString) return null; return new Date(dateString); } /** * Chuyển đổi chuỗi ngày tháng sang tên thứ trong tuần (tiếng Việt). * * Mục đích: dùng để hiển thị nhãn thứ trong tuần trên response trả về kèm tên thứ. * * Đầu vào: ISO 8601 string, ví dụ: * - "2026-05-20" (date only) * - "2026-05-20T07:00:00.000Z" (UTC — lưu ý: có thể lệch ngày nếu server không chạy UTC+7) * - "2026-05-20T07:00:00.000+07:00" (có offset, khuyến nghị dùng để tránh lệch ngày) * * Cách lấy nhanh date string trong JS: * const dateStr = new Date().toISOString(); // "2026-05-20T07:00:00.000Z" * const dateStr = apiResponse.created_at; // Hasura/API trả sẵn ISO string, dùng trực tiếp * * Đầu ra: tên thứ tiếng Việt, hoặc null nếu date rỗng. * * @example * dateStringToDayLabel("2026-05-20T07:00:00.000+07:00") // "Thứ 4" * dateStringToDayLabel("2026-05-17T07:00:00.000+07:00") // "Chủ nhật" * dateStringToDayLabel("") // null */ dateStringToDayLabel(date) { if (!date) return null; return constant_1.LIST_DAY_OF_WEEK_VI[new Date(date).getDay()]; } isValidDateString(dateString) { const date = new Date(dateString); return !Number.isNaN(date.getTime()); } /** * Cộng hoặc trừ một số ngày vào ngày đầu vào và trả về `Date` mới. * * Hàm này không mutate đối tượng `Date` truyền vào. Giá trị ngày được chuẩn hóa * về chuỗi `YYYY-MM-DD`, chuyển sang số ngày tuyệt đối để cộng/trừ, sau đó dựng * lại thành `Date`. * * @param {Date} date Ngày gốc cần tính toán. * @param {number} amount Số ngày cần cộng thêm. Dùng số âm để lùi ngày. * @returns {Date | null} Ngày mới sau khi dịch chuyển, hoặc `null` nếu `date` không hợp lệ. * @memberof PHXDateHelpers */ addDays(date, amount) { if (!date) return null; const baseYmd = this.formatDateHyphen(date); const [year, month, day] = baseYmd.split("-").map(Number); const shifted = this.civilFromDays(this.daysFromCivil(year, month, day) + amount); return this.stringToDate(`${shifted.year}-${this.pad2(shifted.month)}-${this.pad2(shifted.day)}`); } /** * Lấy ngày bắt đầu của lưới calendar tháng theo chuẩn tuần bắt đầu từ thứ Hai. * * Ví dụ: nếu ngày đầu tháng rơi vào thứ Sáu thì hàm sẽ trả về ngày thứ Hai của * cùng hàng đầu tiên trong lịch, để có thể render đủ grid 7 cột. * * @param {Date} firstDateOfMonth Ngày đầu tiên của tháng đang hiển thị. * @returns {Date | null} Ngày bắt đầu của lưới calendar, hoặc `null` nếu đầu vào không hợp lệ. * @memberof PHXDateHelpers */ getGridStartDate(firstDateOfMonth) { if (!firstDateOfMonth) return null; const weekday = this.getWeekdayFromYmdString(this.formatDateHyphen(firstDateOfMonth)); const mondayBasedOffset = (weekday + 6) % 7; return this.addDays(firstDateOfMonth, -mondayBasedOffset); } /** * Kiểm tra một ngày có rơi vào cuối tuần hay không. * * Cuối tuần ở đây gồm: * - Thứ 7 * - Chủ nhật * * @param {string} date Chuỗi ngày đầu vào. * @returns {boolean} `true` nếu là cuối tuần, ngược lại là `false`. * @memberof PHXDateHelpers */ isWeekend(date) { const dayLabel = this.dateStringToDayLabel(date); const normalized = dayLabel === null || dayLabel === void 0 ? void 0 : dayLabel.trim().toLowerCase(); return normalized === "thứ 7" || normalized === "chủ nhật"; } /** * Tính thứ trong tuần từ chuỗi ngày có định dạng `YYYY-MM-DD`. * * Hàm này parse chuỗi ngày thành các phần số rồi chuyển tiếp sang bộ tính weekday nội bộ. * * @private * @param {string} value Chuỗi ngày định dạng `YYYY-MM-DD`. * @returns {number} Chỉ số thứ trong tuần, với `0 = Chủ nhật` và `6 = Thứ 7`. * @memberof PHXDateHelpers */ getWeekdayFromYmdString(value) { const [year, month, day] = value.split("-").map(Number); return this.getWeekdayFromYmd(year, month, day); } /** * Tính thứ trong tuần từ năm, tháng, ngày. * * @private * @param {number} year Năm. * @param {number} month Tháng, tính từ `1` đến `12`. * @param {number} day Ngày trong tháng. * @returns {number} Chỉ số thứ trong tuần, với `0 = Chủ nhật` và `6 = Thứ 7`. * @memberof PHXDateHelpers */ getWeekdayFromYmd(year, month, day) { const days = this.daysFromCivil(year, month, day); return ((days + 4) % 7 + 7) % 7; } /** * Chuyển một ngày dương lịch thành số ngày tuyệt đối theo thuật toán civil date. * * Hàm này phục vụ cho các phép tính cộng/trừ ngày mà không phụ thuộc trực tiếp * vào thao tác mutate của `Date`. * * @private * @param {number} year Năm. * @param {number} month Tháng, tính từ `1` đến `12`. * @param {number} day Ngày trong tháng. * @returns {number} Số ngày tuyệt đối dùng cho tính toán nội bộ. * @memberof PHXDateHelpers */ daysFromCivil(year, month, day) { let y = year; let m = month; y -= m <= 2 ? 1 : 0; const era = y >= 0 ? Math.floor(y / 400) : Math.floor((y - 399) / 400); const yoe = y - era * 400; m = m + (m > 2 ? -3 : 9); const doy = Math.floor((153 * m + 2) / 5) + day - 1; const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy; return era * 146097 + doe - 719468; } /** * Chuyển số ngày tuyệt đối về lại ngày dương lịch. * * @private * @param {number} days Số ngày tuyệt đối. * @returns {{ year: number; month: number; day: number }} Đối tượng ngày tương ứng. * @memberof PHXDateHelpers */ civilFromDays(days) { const z = days + 719468; const era = z >= 0 ? Math.floor(z / 146097) : Math.floor((z - 146096) / 146097); const doe = z - era * 146097; const yoe = Math.floor((doe - Math.floor(doe / 1460) + Math.floor(doe / 36524) - Math.floor(doe / 146096)) / 365); let year = yoe + era * 400; const doy = doe - (365 * yoe + Math.floor(yoe / 4) - Math.floor(yoe / 100)); const mp = Math.floor((5 * doy + 2) / 153); const day = doy - Math.floor((153 * mp + 2) / 5) + 1; const month = mp < 10 ? mp + 3 : mp - 9; year += month <= 2 ? 1 : 0; return { year, month, day }; } /** * Bổ sung số 0 ở đầu để đảm bảo chuỗi số có độ dài 2 ký tự. * * Ví dụ: * - `1` -> `"01"` * - `9` -> `"09"` * - `12` -> `"12"` * * @private * @param {number} value Giá trị số cần chuẩn hóa. * @returns {string} Chuỗi 2 ký tự. * @memberof PHXDateHelpers */ pad2(value) { return String(value).padStart(2, "0"); } }; exports.PHXDateHelpers = PHXDateHelpers; exports.PHXDateHelpers = PHXDateHelpers = __decorate([ (0, common_1.Injectable)() ], PHXDateHelpers); //# sourceMappingURL=helpers.service.js.map