@libs-ui/services-format-date 0.2.356-9 → 0.2.357-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,28 @@
1
- # Format Date Service
1
+ # @libs-ui/services-format-date
2
2
 
3
- Service định dạng ngày giờ dựa trên dayjs. Thin wrapper của `formatDate()` từ `@libs-ui/utils`. Hỗ trợ nhiều kiểu input, định dạng tùy chỉnh, đa ngôn ngữ (vi/en) và format aliases locale-aware.
3
+ > Service Angular định dạng ngày giờ linh hoạt, hỗ trợ nhiều kiểu input, format aliases locale-aware đa ngôn ngữ vi/en.
4
+
5
+ ## Giới thiệu
6
+
7
+ `FormatDateService` là một thin wrapper của hàm `formatDate()` từ `@libs-ui/utils`, được đóng gói thành Angular service để dễ dàng inject qua DI và sử dụng trực tiếp trong template. Service hỗ trợ nhiều kiểu đầu vào (Unix timestamp giây, ISO string, dayjs object), định dạng tùy chỉnh theo chuẩn dayjs, format aliases ngắn gọn tự động chọn format phù hợp theo ngôn ngữ vi/en, cùng cơ chế override toàn cục cho các project cần custom logic.
4
8
 
5
9
  ## Tính năng
6
10
 
7
- - ✅ Input types đa dạng: Unix timestamp (giây), ISO string, dayjs object, Date
11
+ - ✅ Input types đa dạng: Unix timestamp (giây), ISO string, dayjs object
8
12
  - ✅ Format aliases locale-aware: `dmy`, `dmy hm`, `dmy hms`, `my`, `dm`... tự chọn format theo ngôn ngữ
9
- - ✅ Đa ngôn ngữ: vi/en — tiếng Việt ngày trước tháng, tiếng Anh tháng trước ngày
10
- - ✅ Tự lấy ngôn ngữ từ `UtilsCache.getLang()` nếu không truyền
11
- - ✅ null/undefined → trả về `''` (không throw error)
12
- - ✅ Custom format override hook toàn cục (`updateFunctionFormatDate`)
13
+ - ✅ Đa ngôn ngữ: `vi`/`en` — tiếng Việt ngày trước tháng, tiếng Anh tháng trước ngày
14
+ - ✅ Tự động lấy ngôn ngữ từ `UtilsCache.getLang()` nếu không truyền `lang`
15
+ - ✅ `null`/`undefined` → trả về `''` (không throw error)
16
+ - ✅ Custom format override toàn cục qua `updateFunctionFormatDate`
17
+ - ✅ Múi giờ chuẩn hóa qua `getDayjs()` (mặc định `Asia/Ho_Chi_Minh`)
18
+ - ✅ `providedIn: 'root'` — không cần khai báo providers thủ công
19
+
20
+ ## Khi nào sử dụng
21
+
22
+ - Cần inject service để dùng `transform()` trực tiếp trong template Angular (ví dụ: trong computed, `@switch`, binding).
23
+ - Muốn mock service trong unit test — dễ mock hơn hàm utils standalone.
24
+ - Cần format ngày giờ theo ngôn ngữ hiện tại của ứng dụng mà không muốn tự quản lý lang.
25
+ - Cần format date trong TypeScript class thông qua DI (nếu không cần DI, dùng thẳng `formatDate()` từ `@libs-ui/utils`).
13
26
 
14
27
  ## Cài đặt
15
28
 
@@ -23,9 +36,9 @@ npm install @libs-ui/services-format-date
23
36
  import { FormatDateService } from '@libs-ui/services-format-date';
24
37
  ```
25
38
 
26
- ## Cách sử dụng
39
+ ## dụ sử dụng
27
40
 
28
- ### Trong Component
41
+ ### dụ 1 — Cơ bản: Unix timestamp với format mặc định
29
42
 
30
43
  ```typescript
31
44
  import { Component, inject } from '@angular/core';
@@ -33,69 +46,194 @@ import { FormatDateService } from '@libs-ui/services-format-date';
33
46
 
34
47
  @Component({
35
48
  standalone: true,
49
+ changeDetection: ChangeDetectionStrategy.OnPush,
36
50
  template: `
37
51
  <p>{{ formatDateService.transform(timestamp) }}</p>
38
- <p>{{ formatDateService.transform(date, 'dmy hm', 'vi') }}</p>
52
+ <!-- Output: "2024/05/20 17:30" -->
53
+
54
+ <p>{{ formatDateService.transform(timestamp, 'DD/MM/YYYY') }}</p>
55
+ <!-- Output: "20/05/2024" -->
39
56
  `,
40
57
  })
41
58
  export class ExampleComponent {
42
59
  readonly formatDateService = inject(FormatDateService);
43
60
 
44
61
  timestamp = 1716222600; // Unix timestamp (giây)
45
- date = '2024-05-20T10:30:00'; // ISO string
46
62
  }
47
63
  ```
48
64
 
49
- ### Dùng trong TypeScript (khuyến nghị)
65
+ ### dụ 2 — Format aliases locale-aware (vi/en)
66
+
67
+ ```typescript
68
+ import { Component, inject } from '@angular/core';
69
+ import { FormatDateService } from '@libs-ui/services-format-date';
70
+
71
+ @Component({
72
+ standalone: true,
73
+ changeDetection: ChangeDetectionStrategy.OnPush,
74
+ template: `
75
+ <!-- lang='vi': "20 Thg 5, 2024 10:30" -->
76
+ <p>{{ formatDateService.transform(dateStr, 'dmy hm', 'vi') }}</p>
77
+
78
+ <!-- lang='en': "May 20, 2024 10:30" -->
79
+ <p>{{ formatDateService.transform(dateStr, 'dmy hm', 'en') }}</p>
80
+
81
+ <!-- Chỉ ngày tháng năm (vi): "20 Thg 5, 2024" -->
82
+ <p>{{ formatDateService.transform(dateStr, 'dmy', 'vi') }}</p>
83
+
84
+ <!-- Chỉ tháng năm (vi): "Thg 5, 2024" -->
85
+ <p>{{ formatDateService.transform(dateStr, 'my', 'vi') }}</p>
86
+ `,
87
+ })
88
+ export class LocaleExampleComponent {
89
+ readonly formatDateService = inject(FormatDateService);
90
+
91
+ dateStr = '2024-05-20T10:30:00'; // ISO string
92
+ }
93
+ ```
94
+
95
+ ### Ví dụ 3 — Trong TypeScript class (computed, xử lý logic)
96
+
97
+ ```typescript
98
+ import { Component, inject, computed, signal } from '@angular/core';
99
+ import { FormatDateService } from '@libs-ui/services-format-date';
100
+
101
+ @Component({
102
+ standalone: true,
103
+ changeDetection: ChangeDetectionStrategy.OnPush,
104
+ template: `<p>{{ displayDate() }}</p>`,
105
+ })
106
+ export class ComputedExampleComponent {
107
+ private readonly formatDateService = inject(FormatDateService);
108
+
109
+ private rawTimestamp = signal<number>(1716222600);
110
+
111
+ protected displayDate = computed(() =>
112
+ this.formatDateService.transform(this.rawTimestamp(), 'dmy hm', 'vi')
113
+ );
114
+ }
115
+ ```
116
+
117
+ ### Ví dụ 4 — ISO string với format giây
118
+
119
+ ```typescript
120
+ import { Component, inject } from '@angular/core';
121
+ import { FormatDateService } from '@libs-ui/services-format-date';
122
+
123
+ @Component({
124
+ standalone: true,
125
+ changeDetection: ChangeDetectionStrategy.OnPush,
126
+ template: `
127
+ <!-- Output: "20/05/2024 10:30:00" -->
128
+ <p>{{ formatDateService.transform(isoDate, 'DD/MM/YYYY HH:mm:ss') }}</p>
50
129
 
51
- Service là thin wrapper của `formatDate` trong `@libs-ui/utils`. Khi cần dùng trong TypeScript, import thẳng hàm đó — **không cần inject service**:
130
+ <!-- null/undefined '' (không crash) -->
131
+ <p>{{ formatDateService.transform(null) }}</p>
132
+ `,
133
+ })
134
+ export class IsoExampleComponent {
135
+ readonly formatDateService = inject(FormatDateService);
136
+
137
+ isoDate = '2024-05-20T10:30:00';
138
+ }
139
+ ```
140
+
141
+ ### Ví dụ 5 — Không dùng DI: `formatDate()` từ `@libs-ui/utils` (khuyến nghị cho TypeScript thuần)
52
142
 
53
143
  ```typescript
54
144
  import { formatDate } from '@libs-ui/utils';
55
145
 
56
- // Không cần inject service
146
+ // Không inject service — dùng thẳng hàm utils
57
147
  const result = formatDate(1716222600, 'YYYY/MM/DD HH:mm');
58
148
  // Output: '2024/05/20 17:30'
59
149
 
60
- const viDate = formatDate('2024-05-20', 'dmy hm', 'vi');
61
- // Output: '20 Th5, 2024 00:00'
150
+ const viDate = formatDate('2024-05-20T10:30:00', 'dmy hm', 'vi');
151
+ // Output: '20 Thg 5, 2024 10:30'
62
152
 
63
- // Trong component class:
64
- class ExampleComponent {
65
- formattedDate = formatDate(this.rawDate, 'DD/MM/YYYY');
66
- }
153
+ const enDate = formatDate('2024-05-20T10:30:00', 'dmy hm', 'en');
154
+ // Output: 'May 20, 2024 10:30'
67
155
  ```
68
156
 
69
- ## API
157
+ ## Methods (Service)
158
+
159
+ | Method | Signature | Mô tả |
160
+ |---|---|---|
161
+ | `transform` | `transform(time, format?, lang?): string` | Định dạng giá trị thời gian thành chuỗi. Trả về `''` nếu `time` là `null`/`undefined`. |
70
162
 
71
- ### `transform(time, format?, lang?)`
163
+ ### Chi tiết tham số `transform()`
72
164
 
73
- | Parameter | Type | Default | Mô tả |
74
- | --------- | ------------------------------------------------------ | ---------------------- | ---------------------------------------- |
75
- | `time` | `string \| number \| dayjs.Dayjs \| undefined \| null` | - | Giá trị thời gian. null/undefined → `''` |
76
- | `format` | `string` | `'YYYY/MM/DD HH:mm'` | Format dayjs hoặc alias ngắn gọn |
77
- | `lang` | `string \| undefined` | `UtilsCache.getLang()` | Ngôn ngữ: `'vi'` hoặc `'en'` |
165
+ | Tham số | Type | Default | Mô tả |
166
+ |---|---|---|---|
167
+ | `time` | `string \| number \| dayjs.Dayjs \| undefined \| null` | | Giá trị thời gian cần format. `null`/`undefined`trả về `''`. |
168
+ | `format` | `string` | `'YYYY/MM/DD HH:mm'` | Format dayjs chuẩn hoặc alias ngắn gọn (xem bảng Format Aliases). |
169
+ | `lang` | `string \| undefined` | `UtilsCache.getLang()` | Ngôn ngữ: `'vi'` hoặc `'en'`. Không truyền → tự lấy từ cache toàn cục. |
78
170
 
79
- **Returns:** `string` — chuỗi đã format, hoặc `''` nếu input là null/undefined.
171
+ **Returns:** `string` — chuỗi đã format, hoặc `''` nếu input là `null`/`undefined`.
80
172
 
81
173
  ## Format Aliases (locale-aware)
82
174
 
83
- | Alias | Format vi | Format en | Ghi chú |
84
- | ---------- | -------------------------- | -------------------------- | ----------------------- |
85
- | `dmy hm` | `D MMM, YYYY HH:mm` | `MMM D, YYYY HH:mm` | Ngày tháng năm giờ phút |
86
- | `dmy` | `D MMM, YYYY` | `MMM D, YYYY` | Ngày tháng năm |
87
- | `dm` | `D MMM` | `MMM D` | Ngày tháng |
88
- | `my` | `MMM, YYYY` | `MMM YYYY` | Tháng năm |
89
- | `dmy hms` | `D MMM, YYYY HH:mm:ss` | `MMM D, YYYY HH:mm:ss` | Có giây |
90
- | `dmy hmsS` | `D MMM, YYYY HH:mm:ss:SSS` | `MMM D, YYYY HH:mm:ss:SSS` | Có millisecond |
91
- | `HH:mm` | `HH:mm` | `HH:mm` | 24h format |
92
- | `HH:mm A` | `HH:mm A` | `HH:mm A` | 12h AM/PM |
175
+ Các alias dưới đây tự động chọn format phù hợp theo ngôn ngữ (`lang`). Format string trực tiếp (như `DD/MM/YYYY`) không phụ thuộc ngôn ngữ.
93
176
 
94
- Format string trực tiếp (như `DD/MM/YYYY`, `YYYY-MM-DD`...) cũng được hỗ trợ không locale-aware.
177
+ | Alias | Format `vi` | Format `en` | Ghi chú |
178
+ |---|---|---|---|
179
+ | `dmy hm` | `D MMM, YYYY HH:mm` | `MMM D, YYYY HH:mm` | Ngày tháng năm giờ phút |
180
+ | `dmy` | `D MMM, YYYY` | `MMM D, YYYY` | Ngày tháng năm |
181
+ | `dm` | `D MMM` | `MMM D` | Ngày tháng |
182
+ | `my` | `MMM, YYYY` | `MMM YYYY` | Tháng năm |
183
+ | `dmy hms` | `D MMM, YYYY HH:mm:ss` | `MMM D, YYYY HH:mm:ss` | Có giây |
184
+ | `dmy hmsS` | `D MMM, YYYY HH:mm:ss:SSS` | `MMM D, YYYY HH:mm:ss:SSS` | Có millisecond |
185
+ | `HH:mm` | `HH:mm` | `HH:mm` | 24h format |
186
+ | `HH:mm A` | `HH:mm A` | `HH:mm A` | 12h AM/PM |
187
+
188
+ **Các format string tương đương được map tự động:**
189
+
190
+ | Format string truyền vào | Map sang alias |
191
+ |---|---|
192
+ | `DD/MM/YYYY`, `YYYY-MM-DD`, `dd/MM/yyyy` | `dmy` |
193
+ | `MM-DD`, `dd/MM`, `dd/mm` | `dm` |
194
+ | `M/YYYY`, `YYYY-MM`, `MM/yyyy` | `my` |
195
+ | `YYYY/MM/DD hh:mm:ss`, `dd/mm/yyyy hh:mm:ss` | `dmy hms` |
196
+ | Bất kỳ format khác không thuộc danh sách trên | Mặc định map sang `dmy hm` |
197
+
198
+ ## Types & Interfaces
199
+
200
+ ```typescript
201
+ import { TYPE_FUNCTION_FORMAT_DATE } from '@libs-ui/utils';
202
+
203
+ // Type của hàm custom override (dùng với updateFunctionFormatDate)
204
+ // type TYPE_FUNCTION_FORMAT_DATE = (time: dayjs.ConfigType, formatOutput: string, lang?: string) => string;
205
+ ```
206
+
207
+ ## Custom Override toàn cục
208
+
209
+ Dùng `updateFunctionFormatDate` từ `@libs-ui/utils` để override toàn bộ logic format — chạy một lần khi app khởi động:
210
+
211
+ ```typescript
212
+ import { updateFunctionFormatDate } from '@libs-ui/utils';
213
+
214
+ // Trong AppComponent hoặc app initializer:
215
+ updateFunctionFormatDate((time, format, lang) => {
216
+ // Custom format logic của project
217
+ return myCustomFormatter(time, format, lang);
218
+ });
219
+ ```
95
220
 
96
221
  ## Lưu ý quan trọng
97
222
 
98
- - **Inject service hay dùng thẳng utils?** Nếu chỉ cần trong TypeScript class, dùng thẳng `formatDate()` từ `@libs-ui/utils` — không inject service. Inject service khi cần DI (mock test) hoặc dùng trong template qua service reference.
99
- - **lang** không truyền → tự lấy từ `UtilsCache.getLang()`. Đảm bảo set ngôn ngữ global trước khi dùng.
100
- - **Unix timestamp**số nguyên **giây** (không phải milliseconds). `Date.now()` trả về ms chia 1000.
101
- - **Format aliases** chỉ có tác dụng locale-aware khi dùng với `lang='vi'` hoặc `lang='en'`. Format string trực tiếp không phụ thuộc ngôn ngữ.
223
+ ⚠️ **Inject service hay dùng thẳng utils?**: Nếu chỉ cần format date trong TypeScript (không trong template hoặc không cần DI/mock), dùng thẳng `formatDate()` từ `@libs-ui/utils`. Inject `FormatDateService` khi cần DI (mock test) hoặc dùng trong Angular template qua service reference.
224
+
225
+ ⚠️ **Unix timestamp là giây, không phải milliseconds**: `Date.now()` trả về milliseconds. Khi dùng JS timestamp làm input, phải chia 1000: `service.transform(Date.now() / 1000)`.
226
+
227
+ ⚠️ **lang không truyền → tự lấy từ UtilsCache**: Đảm bảo ngôn ngữ global đã được set trước khi dùng service (thường trong AppComponent hoặc i18n setup). Nếu chưa set, format aliases có thể không trả về đúng locale.
228
+
229
+ ⚠️ **Format aliases chỉ locale-aware khi truyền `lang='vi'` hoặc `lang='en'`**: Format string trực tiếp như `DD/MM/YYYY HH:mm` không phụ thuộc ngôn ngữ, luôn cho cùng kết quả bất kể `lang`.
230
+
231
+ ⚠️ **Múi giờ mặc định `Asia/Ho_Chi_Minh`**: Service dùng `getDayjs()` đã cấu hình timezone. Để đổi timezone toàn cục, gọi `setDefaultTimeZone('America/New_York')` từ `@libs-ui/utils` trước khi dùng.
232
+
233
+ ## Demo
234
+
235
+ ```bash
236
+ npx nx serve core-ui
237
+ ```
238
+
239
+ Truy cập: http://localhost:4500/services/format-date
@@ -1 +1 @@
1
- {"version":3,"file":"libs-ui-services-format-date.mjs","sources":["../../../../../libs-ui/services/format-date/src/format-date.service.ts","../../../../../libs-ui/services/format-date/src/libs-ui-services-format-date.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { formatDate } from '@libs-ui/utils';\nimport dayjs from 'dayjs';\n\n@Injectable({ providedIn: 'root' })\nexport class FormatDateService {\n public transform(time: string | number | dayjs.Dayjs | undefined | null, format = 'YYYY/MM/DD HH:mm', lang?: string): string {\n return formatDate(time, format, lang) || '';\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAKa,iBAAiB,CAAA;AACrB,IAAA,SAAS,CAAC,IAAsD,EAAE,MAAM,GAAG,kBAAkB,EAAE,IAAa,EAAA;QACjH,OAAO,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE;IAC7C;wGAHW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cADJ,MAAM,EAAA,CAAA;;4FACnB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACJlC;;AAEG;;;;"}
1
+ {"version":3,"file":"libs-ui-services-format-date.mjs","sources":["../../../../../libs-ui/services/format-date/src/format-date.service.ts","../../../../../libs-ui/services/format-date/src/libs-ui-services-format-date.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { formatDate } from '@libs-ui/utils';\nimport dayjs from 'dayjs';\n\n@Injectable({ providedIn: 'root' })\nexport class FormatDateService {\n public transform(time: string | number | dayjs.Dayjs | undefined | null, format = 'YYYY/MM/DD HH:mm', lang?: string): string {\n return formatDate(time, format, lang) || '';\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAKa,iBAAiB,CAAA;AACrB,IAAA,SAAS,CAAC,IAAsD,EAAE,MAAM,GAAG,kBAAkB,EAAE,IAAa,EAAA;QACjH,OAAO,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;KAC7C;wGAHU,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAjB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cADJ,MAAM,EAAA,CAAA,CAAA;;4FACnB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;;;ACJlC;;AAEG;;;;"}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@libs-ui/services-format-date",
3
- "version": "0.2.356-9",
3
+ "version": "0.2.357-1",
4
4
  "peerDependencies": {
5
5
  "@angular/core": ">=18.0.0",
6
6
  "dayjs": "1.11.5",
7
- "@libs-ui/utils": "0.2.356-9"
7
+ "@libs-ui/utils": "0.2.357-1"
8
8
  },
9
9
  "sideEffects": false,
10
10
  "module": "fesm2022/libs-ui-services-format-date.mjs",