phx-node
Version:
PHX NODE
301 lines • 12.9 kB
JavaScript
;
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