1
- import { useI18n } from "vue-i18n" ;
2
- import { type UseTimeAgoMessages , type UseTimeAgoUnitNamesDefault } from "@vueuse/core" ;
1
+ import { format , formatDistance } from "date-fns" ;
2
+ /* eslint import/namespace: ['error', { allowComputed: true }] */
3
+ import * as Locales from "date-fns/locale" ;
3
4
4
5
const cache = {
5
6
currency : "" ,
@@ -20,105 +21,63 @@ export async function useFormatCurrency() {
20
21
}
21
22
}
22
23
23
- return ( value : number | string ) => fmtCurrency ( value , cache . currency ) ;
24
+ return ( value : number | string ) => fmtCurrency ( value , cache . currency , getLocaleCode ( ) ) ;
24
25
}
25
26
26
27
export type DateTimeFormat = "relative" | "long" | "short" | "human" ;
27
28
export type DateTimeType = "date" | "time" | "datetime" ;
28
29
29
- function ordinalIndicator ( num : number ) {
30
- if ( num > 3 && num < 21 ) return "th" ;
31
- switch ( num % 10 ) {
32
- case 1 :
33
- return "st" ;
34
- case 2 :
35
- return "nd" ;
36
- case 3 :
37
- return "rd" ;
38
- default :
39
- return "th" ;
40
- }
30
+ export function getLocaleCode ( ) {
31
+ const { $i18nGlobal } = useNuxtApp ( ) ;
32
+ return ( $i18nGlobal ?. locale ?. value as string ) ?? "en-US" ;
41
33
}
42
34
43
- export function useLocaleTimeAgo ( date : Date ) {
44
- const { t } = useI18n ( ) ;
45
-
46
- const I18N_MESSAGES : UseTimeAgoMessages < UseTimeAgoUnitNamesDefault > = {
47
- justNow : t ( "components.global.date_time.just-now" ) ,
48
- past : n => ( n . match ( / \d / ) ? t ( "components.global.date_time.ago" , [ n ] ) : n ) ,
49
- future : n => ( n . match ( / \d / ) ? t ( "components.global.date_time.in" , [ n ] ) : n ) ,
50
- month : ( n , past ) =>
51
- n === 1
52
- ? past
53
- ? t ( "components.global.date_time.last-month" )
54
- : t ( "components.global.date_time.next-month" )
55
- : `${ n } ${ t ( `components.global.date_time.months` ) } ` ,
56
- year : ( n , past ) =>
57
- n === 1
58
- ? past
59
- ? t ( "components.global.date_time.last-year" )
60
- : t ( "components.global.date_time.next-year" )
61
- : `${ n } ${ t ( `components.global.date_time.years` ) } ` ,
62
- day : ( n , past ) =>
63
- n === 1
64
- ? past
65
- ? t ( "components.global.date_time.yesterday" )
66
- : t ( "components.global.date_time.tomorrow" )
67
- : `${ n } ${ t ( `components.global.date_time.days` ) } ` ,
68
- week : ( n , past ) =>
69
- n === 1
70
- ? past
71
- ? t ( "components.global.date_time.last-week" )
72
- : t ( "components.global.date_time.next-week" )
73
- : `${ n } ${ t ( `components.global.date_time.weeks` ) } ` ,
74
- hour : n => `${ n } ${ n === 1 ? t ( "components.global.date_time.hour" ) : t ( "components.global.date_time.hours" ) } ` ,
75
- minute : n => `${ n } ${ n === 1 ? t ( "components.global.date_time.minute" ) : t ( "components.global.date_time.minutes" ) } ` ,
76
- second : n => `${ n } ${ n === 1 ? t ( "components.global.date_time.second" ) : t ( "components.global.date_time.seconds" ) } ` ,
77
- invalid : "" ,
78
- } ;
79
-
80
- return useTimeAgo ( date , {
81
- fullDateFormatter : ( date : Date ) => date . toLocaleDateString ( ) ,
82
- messages : I18N_MESSAGES ,
83
- } ) ;
35
+ function getLocaleForDate ( ) {
36
+ const localeCode = getLocaleCode ( ) ;
37
+ const lang = localeCode . length > 1 ? localeCode . substring ( 0 , 2 ) : localeCode ;
38
+ const region = localeCode . length > 2 ? localeCode . substring ( 3 ) : "" ;
39
+ return Locales [ ( lang + region ) as keyof typeof Locales ] ?? Locales [ lang as keyof typeof Locales ] ?? Locales . enUS ;
84
40
}
85
41
86
- export function fmtDate ( value : string | Date , fmt : DateTimeFormat = "human" ) : string {
87
- const months = [
88
- "January" ,
89
- "February" ,
90
- "March" ,
91
- "April" ,
92
- "May" ,
93
- "June" ,
94
- "July" ,
95
- "August" ,
96
- "September" ,
97
- "October" ,
98
- "November" ,
99
- "December" ,
100
- ] ;
101
-
102
- const dt = typeof value === "string" ? new Date ( value ) : value ;
103
- if ( ! dt ) {
42
+ export function fmtDate (
43
+ value : string | Date | number ,
44
+ fmt : DateTimeFormat = "human" ,
45
+ type : DateTimeType = "date"
46
+ ) : string {
47
+ const dt = typeof value === "string" || typeof value === "number" ? new Date ( value ) : value ;
48
+
49
+ if ( ! dt || ! validDate ( dt ) ) {
104
50
return "" ;
105
51
}
106
52
107
- if ( ! validDate ( dt ) ) {
108
- return "" ;
53
+ const localeOptions = { locale : getLocaleForDate ( ) } ;
54
+
55
+ if ( fmt === "relative" ) {
56
+ return `${ formatDistance ( dt , new Date ( ) , { ...localeOptions , addSuffix : true } ) } (${ fmtDate ( dt , "short" , "date" ) } )` ;
57
+ }
58
+
59
+ if ( type === "time" ) {
60
+ return format ( dt , "p" , localeOptions ) ;
109
61
}
110
62
63
+ let formatStr = "" ;
64
+
111
65
switch ( fmt ) {
112
- case "relative" :
113
- return useLocaleTimeAgo ( dt ) . value + useDateFormat ( dt , " (YYYY-MM-DD)" ) . value ;
66
+ case "human" :
67
+ formatStr = "PPP" ;
68
+ break ;
114
69
case "long" :
115
- return useDateFormat ( dt , "YYYY-MM-DD (dddd)" ) . value ;
70
+ formatStr = "PP" ;
71
+ break ;
116
72
case "short" :
117
- return useDateFormat ( dt , "YYYY-MM-DD" ) . value ;
118
- case "human" :
119
- // January 1st, 2021
120
- return `${ months [ dt . getMonth ( ) ] } ${ dt . getDate ( ) } ${ ordinalIndicator ( dt . getDate ( ) ) } , ${ dt . getFullYear ( ) } ` ;
73
+ formatStr = "P" ;
74
+ break ;
121
75
default :
122
76
return "" ;
123
77
}
78
+ if ( type === "datetime" ) {
79
+ formatStr += "p" ;
80
+ }
81
+
82
+ return format ( dt , formatStr , localeOptions ) ;
124
83
}
0 commit comments