- Introduced backend patterns skill with guidelines on API design, database optimization, and server-side best practices. - Added coding standards skill outlining universal coding principles for TypeScript, NestJS, and Node.js development. - Implemented continuous learning skill to automatically extract reusable patterns from Cursor sessions. - Created NestJS best practices skill detailing architecture patterns, dependency injection, error handling, and security measures. - Included various rules and templates for NestJS best practices to ensure production-ready applications.
54 lines
2.5 KiB
Plaintext
54 lines
2.5 KiB
Plaintext
---
|
|
description: All date-related data must use DateTime; never add parallel date files or helpers — extend the VO instead
|
|
alwaysApply: true
|
|
---
|
|
|
|
# DateTime Value Object
|
|
|
|
## Mandatory
|
|
|
|
ALL data related to dates or date-times in the domain and application layers MUST use `DateTime` from `src/common/value-objects/date-time/`.
|
|
|
|
- Construct from HTTP ISO via `DateTime.create(raw)`
|
|
- Reconstruct from DB via `DateTime.fromUnixMs(ms)`
|
|
- Compare with `equals()`, persist with `value` / `toJSON()` (unix **milliseconds**, UTC instant)
|
|
- Render with `format()` / `toString()` using `DEFAULT_TIMEZONE` (default `GMT+7`) — timezone is for display and naive ISO interpretation only
|
|
|
|
There is one date abstraction in this codebase: `DateTime`. Use it for every timestamp, occurrence, schedule instant, created/updated field, and any other date-related value in domain/application code.
|
|
|
|
## Forbidden
|
|
|
|
Do NOT:
|
|
|
|
- Store or pass date-times as plain `string` / `number` / built-in `Date` in domain models, services, or repositories (beyond the DTO/HTTP or DB number boundary)
|
|
- Create **any** new file or function for date parsing, validation, formatting, timezone conversion, or comparison
|
|
- Add pipes, decorators, utils, helpers, or modules that bypass the VO
|
|
- Use date libraries (`date-fns`, `luxon`, `moment`, `dayjs`, Temporal polyfills, etc.)
|
|
|
|
```typescript
|
|
// BAD — new helper / parallel logic
|
|
function parseDate(raw: string): number { /* ... */ }
|
|
function formatDate(ms: number): string { /* ... */ }
|
|
user.occurredAt = Date.parse(dto.occurredAt)
|
|
|
|
// GOOD — DateTime only
|
|
const occurredAt = DateTime.create(dto.occurredAt)
|
|
user.occurredAt = occurredAt // DateTime in domain
|
|
await repo.save({ occurredAt: occurredAt.value }) // unix ms only at persistence edge
|
|
```
|
|
|
|
## When the VO is not enough
|
|
|
|
If a requirement cannot be met with the current VO (e.g. new input formats, formatting options, comparisons, timezone forms):
|
|
|
|
1. **Update** `src/common/value-objects/date-time/` (implementation + colocated tests) to match the requirement
|
|
2. Do **not** create a new file, function, type, helper, or module for dates
|
|
|
|
## Boundaries
|
|
|
|
- HTTP DTOs may accept ISO `string`; map to `DateTime.create()` at the service boundary
|
|
- Database columns may store unix milliseconds (`bigint` / integer); map to/from `DateTime` in the repository
|
|
- Naive ISO strings (no `Z` / offset) are interpreted in `DEFAULT_TIMEZONE`
|
|
- `InvalidDateTimeError` is the only date validation error; do not echo raw input in messages
|
|
- Canonical storage is always UTC; never persist the display timezone as the instant
|