@libs-ui/services-format-date 0.2.356-9 → 0.2.357-0
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 +181 -43
- package/fesm2022/libs-ui-services-format-date.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @libs-ui/services-format-date
|
|
2
2
|
|
|
3
|
-
Service định dạng ngày giờ
|
|
3
|
+
> Service Angular định dạng ngày giờ linh hoạt, hỗ trợ nhiều kiểu input, format aliases locale-aware và đ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
|
|
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
|
|
10
|
-
- ✅ Tự lấy ngôn ngữ từ `UtilsCache.getLang()` nếu không truyền
|
|
11
|
-
- ✅ null
|
|
12
|
-
- ✅ Custom format override
|
|
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
|
-
##
|
|
39
|
+
## Ví dụ sử dụng
|
|
27
40
|
|
|
28
|
-
###
|
|
41
|
+
### Ví 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
|
-
|
|
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
|
-
###
|
|
65
|
+
### Ví 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
|
-
|
|
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
|
|
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-
|
|
61
|
-
// Output: '20
|
|
150
|
+
const viDate = formatDate('2024-05-20T10:30:00', 'dmy hm', 'vi');
|
|
151
|
+
// Output: '20 Thg 5, 2024 10:30'
|
|
62
152
|
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
##
|
|
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(
|
|
163
|
+
### Chi tiết tham số `transform()`
|
|
72
164
|
|
|
73
|
-
|
|
|
74
|
-
|
|
75
|
-
| `time`
|
|
76
|
-
| `format`
|
|
77
|
-
| `lang`
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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;
|
|
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.
|
|
3
|
+
"version": "0.2.357-0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/core": ">=18.0.0",
|
|
6
6
|
"dayjs": "1.11.5",
|
|
7
|
-
"@libs-ui/utils": "0.2.
|
|
7
|
+
"@libs-ui/utils": "0.2.357-0"
|
|
8
8
|
},
|
|
9
9
|
"sideEffects": false,
|
|
10
10
|
"module": "fesm2022/libs-ui-services-format-date.mjs",
|