DateUtility
Overview
The DateUtility provides a pre-configured Day.js instance with essential plugins for timezone-aware date manipulation. All backend services import dayjs from @nx/core to ensure consistent date handling across the system.
Source: packages/core/src/utilities/date.utility.ts (23 lines)
Source
The entire module is 23 lines -- a pre-configured singleton export:
typescript
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import isoWeek from 'dayjs/plugin/isoWeek';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
dayjs.extend(customParseFormat);
dayjs.extend(timezone);
dayjs.extend(isoWeek);
dayjs.extend(utc);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);
const tz = process.env.APP_ENV_APPLICATION_TIMEZONE ?? 'Asia/Ho_Chi_Minh';
dayjs.tz.setDefault(tz);
export { dayjs };Configuration
Default Timezone
The default timezone is Asia/Ho_Chi_Minh (UTC+7). It can be overridden via the APP_ENV_APPLICATION_TIMEZONE environment variable.
| Variable | Required | Default | Description |
|---|---|---|---|
APP_ENV_APPLICATION_TIMEZONE | No | Asia/Ho_Chi_Minh | IANA timezone identifier |
bash
# .env.development
APP_ENV_APPLICATION_TIMEZONE=Asia/Ho_Chi_Minh # Default
APP_ENV_APPLICATION_TIMEZONE=America/New_York # Override for US Eastern
APP_ENV_APPLICATION_TIMEZONE=UTC # UTC modeLoaded Plugins
| Plugin | Purpose | Example |
|---|---|---|
customParseFormat | Parse dates with custom format strings | dayjs('20/01/2025', 'DD/MM/YYYY') |
timezone | Timezone conversion and awareness | dayjs().tz('Asia/Tokyo') |
isoWeek | ISO week number calculations | dayjs().isoWeek() |
utc | UTC mode operations | dayjs.utc() |
isSameOrBefore | Inclusive "before" comparison | date.isSameOrBefore(other) |
isSameOrAfter | Inclusive "after" comparison | date.isSameOrAfter(other) |
Import
typescript
import { dayjs } from '@nx/core';
// or
import { dayjs } from '@nx/core/utilities';Basic Usage
Current Date/Time
typescript
// Current time in default timezone (Asia/Ho_Chi_Minh)
const now = dayjs();
// Current time in UTC
const utcNow = dayjs.utc();
// Current time in a specific timezone
const tokyoNow = dayjs().tz('Asia/Tokyo');Parse Dates
typescript
// ISO string
const date1 = dayjs('2025-01-20T10:00:00Z');
// Custom format (requires customParseFormat plugin)
const date2 = dayjs('20/01/2025', 'DD/MM/YYYY');
// From timestamp
const date3 = dayjs(1705708800000);
// From Date object
const date4 = dayjs(new Date());Format Dates
typescript
const date = dayjs('2025-01-20T15:30:00');
date.format('YYYY-MM-DD'); // "2025-01-20"
date.format('DD/MM/YYYY'); // "20/01/2025"
date.format('YYYY-MM-DD HH:mm:ss'); // "2025-01-20 15:30:00"
date.format('YYYY-MM-DD HH:mm:ss Z'); // "2025-01-20 15:30:00 +07:00"Timezone Operations
Convert Between Timezones
typescript
const date = dayjs('2025-01-20T10:00:00Z'); // UTC
// Convert to Vietnam time
const vnTime = date.tz('Asia/Ho_Chi_Minh');
vnTime.format('HH:mm'); // "17:00"
// Convert to US Eastern
const etTime = date.tz('America/New_York');
etTime.format('HH:mm'); // "05:00"Store and Display Pattern
typescript
// Store in UTC (for database)
const stored = dayjs().utc().toISOString();
// "2025-01-20T08:30:00.000Z"
// Display in user's timezone
const displayTime = dayjs(stored).tz('Asia/Ho_Chi_Minh').format('HH:mm DD/MM/YYYY');
// "15:30 20/01/2025"Timezone Flow
Date Comparisons
Basic Comparisons
typescript
const date1 = dayjs('2025-01-20');
const date2 = dayjs('2025-01-25');
date1.isBefore(date2); // true
date1.isAfter(date2); // false
date1.isSame(date2); // false
date1.isSame(date2, 'month'); // true (same month)Same or Before/After
These methods come from the isSameOrBefore and isSameOrAfter plugins:
typescript
const startDate = dayjs('2025-01-01');
const endDate = dayjs('2025-01-31');
const checkDate = dayjs('2025-01-15');
// Check if within an inclusive range
const isInRange =
checkDate.isSameOrAfter(startDate) &&
checkDate.isSameOrBefore(endDate);
// trueCompare with Granularity
typescript
const date1 = dayjs('2025-01-20 10:00');
const date2 = dayjs('2025-01-20 15:00');
date1.isSame(date2, 'day'); // true (same day)
date1.isSame(date2, 'hour'); // false (different hour)
date1.isBefore(date2, 'hour'); // trueDate Manipulation
Add/Subtract
typescript
const date = dayjs('2025-01-20');
date.add(7, 'day').format('YYYY-MM-DD'); // "2025-01-27"
date.add(1, 'month').format('YYYY-MM-DD'); // "2025-02-20"
date.subtract(1, 'year').format('YYYY-MM-DD'); // "2024-01-20"
// Chaining
date.add(1, 'month').add(15, 'day').format('YYYY-MM-DD');
// "2025-03-07"Start/End of Period
typescript
const date = dayjs('2025-01-20 15:30:45');
date.startOf('day').format('YYYY-MM-DD HH:mm:ss');
// "2025-01-20 00:00:00"
date.endOf('day').format('YYYY-MM-DD HH:mm:ss');
// "2025-01-20 23:59:59"
date.startOf('month').format('YYYY-MM-DD');
// "2025-01-01"
date.endOf('month').format('YYYY-MM-DD');
// "2025-01-31"ISO Week Operations
The isoWeek plugin provides ISO 8601 week calculations:
typescript
const date = dayjs('2025-01-20');
date.isoWeek(); // 4 (ISO week number)
date.isoWeekday(); // 1 (Monday = 1, Sunday = 7)
date.isoWeekYear(); // 2025
// Get start of ISO week (Monday)
const weekStart = date.startOf('isoWeek');
weekStart.format('YYYY-MM-DD'); // "2025-01-20" (Monday)
// Get end of ISO week (Sunday)
const weekEnd = date.endOf('isoWeek');
weekEnd.format('YYYY-MM-DD'); // "2025-01-26" (Sunday)Common Use Cases
Event Date Validation
typescript
function isEventDateValid(eventDate: string): boolean {
const event = dayjs(eventDate);
const now = dayjs();
const maxFutureDate = now.add(1, 'year');
return event.isAfter(now) && event.isBefore(maxFutureDate);
}Date Range for Reports
typescript
function getMonthlyReportRange(year: number, month: number) {
const start = dayjs()
.year(year)
.month(month - 1)
.startOf('month');
const end = start.endOf('month');
return {
start: start.toISOString(),
end: end.toISOString(),
};
}Database Integration
typescript
// Store in UTC
async createEvent(data: CreateEventDto) {
const eventDateUtc = dayjs
.tz(data.eventDate, data.timezone)
.utc()
.toISOString();
return this.eventRepository.create({
data: {
...data,
eventDate: eventDateUtc,
},
});
}
// Query by date range
const weekStart = dayjs().startOf('isoWeek').toISOString();
const weekEnd = dayjs().endOf('isoWeek').toISOString();
const events = await eventRepository.find({
where: {
eventDate: { gte: weekStart, lte: weekEnd },
},
});Best Practices
1. Always Store UTC
typescript
// Correct -- store in UTC
const stored = dayjs.tz(userInput, userTimezone).utc().toISOString();
// Avoid -- timezone-ambiguous
const stored = dayjs(userInput).format();2. Parse with Explicit Timezone
typescript
// Correct -- explicit timezone
const date = dayjs.tz('2025-01-20 15:00', 'Asia/Ho_Chi_Minh');
// Avoid -- ambiguous
const date = dayjs('2025-01-20 15:00'); // Which timezone?3. Use ISO Format for API Responses
typescript
// Correct -- machine-readable
{ createdAt: dayjs(record.createdAt).toISOString() }
// "2025-01-20T08:30:00.000Z"
// Avoid -- locale-specific
{ createdAt: dayjs(record.createdAt).format('DD/MM/YYYY') }
// "20/01/2025"IGNIS Framework Reference
The dayjs instance exported by @nx/core builds on the IGNIS Date utility. For the base utility documentation, see: