2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Japanese era support
5 * COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
13 #define JAPANESE_ERA_MAX 16
15 /* #define DONT_USE_REGISTRY */
17 static DWORD s_JapaneseEraCount
= 0;
18 static JAPANESE_ERA s_JapaneseEraTable
[JAPANESE_ERA_MAX
]
19 #ifdef DONT_USE_REGISTRY
22 {1868, 1, 1, {0x660E, 0x6CBB}, {0x660E, 0}, L
"Meiji", L
"M"},
23 {1912, 7, 30, {0x5927, 0x6B63}, {0x5927, 0}, L
"Taisho", L
"T"},
24 {1926, 12, 25, {0x662D, 0x548C}, {0x662D, 0}, L
"Showa", L
"S"},
25 {1989, 1, 8, {0x5E73, 0x6210}, {0x5E73, 0}, L
"Heisei", L
"H"},
26 {2019, 5, 1, {0x4EE4, 0x548C}, {0x4EE4, 0}, L
"Reiwa", L
"R"},
31 HANDLE
NLS_RegOpenKey(HANDLE hRootKey
, LPCWSTR szKeyName
);
33 BOOL
NLS_RegEnumValue(HANDLE hKey
, UINT ulIndex
,
34 LPWSTR szValueName
, ULONG valueNameSize
,
35 LPWSTR szValueData
, ULONG valueDataSize
);
37 static INT
JapaneseEra_Compare(const void *e1
, const void *e2
)
39 PCJAPANESE_ERA pEra1
= (PCJAPANESE_ERA
)e1
;
40 PCJAPANESE_ERA pEra2
= (PCJAPANESE_ERA
)e2
;
41 if (pEra1
->wYear
< pEra2
->wYear
)
43 if (pEra1
->wYear
> pEra2
->wYear
)
45 if (pEra1
->wMonth
< pEra2
->wMonth
)
47 if (pEra1
->wMonth
> pEra2
->wMonth
)
49 if (pEra1
->wDay
< pEra2
->wDay
)
51 if (pEra1
->wDay
> pEra2
->wDay
)
56 BOOL
JapaneseEra_IsFirstYearGannen(void)
58 #ifdef DONT_USE_REGISTRY
63 WCHAR szName
[32], szValue
[32];
64 static BOOL s_bIsCached
= FALSE
, s_bFirstIsGannen
= TRUE
;
67 return s_bFirstIsGannen
;
69 KeyHandle
= NLS_RegOpenKey(NULL
, L
"\\Registry\\Machine\\System\\"
70 L
"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese");
74 for (dwIndex
= 0; dwIndex
< 16; ++dwIndex
)
76 if (!NLS_RegEnumValue(KeyHandle
, dwIndex
, szName
, sizeof(szName
),
77 szValue
, sizeof(szValue
)))
82 if (lstrcmpiW(szName
, L
"InitialEraYear") == 0)
84 s_bFirstIsGannen
= (szValue
[0] == 0x5143);
90 return s_bFirstIsGannen
;
96 * https://en.wikipedia.org/wiki/Japanese_era_name
97 * https://docs.microsoft.com/en-us/windows/desktop/Intl/era-handling-for-the-japanese-calendar
99 static PCJAPANESE_ERA
JapaneseEra_Load(DWORD
*pdwCount
)
101 #ifndef DONT_USE_REGISTRY
104 WCHAR szName
[128], szValue
[128];
105 JAPANESE_ERA
*pEntry
;
106 LPWSTR pch1
, pch2
, pch3
, pch4
;
109 ASSERT(pdwCount
!= NULL
);
111 /* return cache if any */
112 if (s_JapaneseEraCount
!= 0)
114 *pdwCount
= s_JapaneseEraCount
;
115 return s_JapaneseEraTable
;
118 #ifdef DONT_USE_REGISTRY
119 s_JapaneseEraCount
= ARRAYSIZE(s_JapaneseEraTable
);
123 RtlZeroMemory(&s_JapaneseEraTable
, sizeof(s_JapaneseEraTable
));
125 /* open registry key */
126 KeyHandle
= NLS_RegOpenKey(NULL
, L
"\\Registry\\Machine\\System\\"
127 L
"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese\\Eras");
132 for (dwIndex
= 0; dwIndex
< JAPANESE_ERA_MAX
; ++dwIndex
)
134 pEntry
= &s_JapaneseEraTable
[dwIndex
];
136 /* get name and data */
137 if (!NLS_RegEnumValue(KeyHandle
, dwIndex
, szName
, sizeof(szName
),
138 szValue
, sizeof(szValue
)))
145 pch2
= wcschr(pch1
, L
' ');
150 *pch2
++ = UNICODE_NULL
;
152 pch3
= wcschr(pch2
, L
' ');
157 *pch3
++ = UNICODE_NULL
;
159 pEntry
->wYear
= _wtoi(pch1
);
160 pEntry
->wMonth
= _wtoi(pch2
);
161 pEntry
->wDay
= _wtoi(pch3
);
162 if (pEntry
->wYear
== 0 || pEntry
->wMonth
== 0 || pEntry
->wDay
== 0)
169 pch2
= wcschr(pch1
, L
'_');
174 *pch2
++ = UNICODE_NULL
;
176 pch3
= wcschr(pch2
, L
'_');
181 *pch3
++ = UNICODE_NULL
;
183 pch4
= wcschr(pch3
, L
'_');
188 *pch4
++ = UNICODE_NULL
;
191 RtlStringCbCopyW(pEntry
->szEraName
, sizeof(pEntry
->szEraName
), pch1
);
192 RtlStringCbCopyW(pEntry
->szEraAbbrev
, sizeof(pEntry
->szEraAbbrev
), pch2
);
193 RtlStringCbCopyW(pEntry
->szEnglishEraName
, sizeof(pEntry
->szEnglishEraName
), pch3
);
194 RtlStringCbCopyW(pEntry
->szEnglishEraAbbrev
, sizeof(pEntry
->szEnglishEraAbbrev
), pch4
);
201 qsort(s_JapaneseEraTable
, s_JapaneseEraCount
, sizeof(JAPANESE_ERA
),
202 JapaneseEra_Compare
);
205 s_JapaneseEraCount
= dwIndex
;
208 *pdwCount
= s_JapaneseEraCount
;
210 return s_JapaneseEraTable
;
213 static BOOL
JapaneseEra_ToSystemTime(PCJAPANESE_ERA pEra
, LPSYSTEMTIME pst
)
215 ASSERT(pEra
!= NULL
);
218 ZeroMemory(pst
, sizeof(*pst
));
219 pst
->wYear
= pEra
->wYear
;
220 pst
->wMonth
= pEra
->wMonth
;
221 pst
->wDay
= pEra
->wDay
;
225 PCJAPANESE_ERA
JapaneseEra_Find(const SYSTEMTIME
*pst OPTIONAL
)
227 DWORD dwIndex
, dwCount
= 0;
228 PCJAPANESE_ERA pTable
, pEntry
, pPrevEntry
= NULL
;
239 SystemTimeToFileTime(pst
, &ft1
);
242 pTable
= JapaneseEra_Load(&dwCount
);
243 if (pTable
== NULL
|| dwCount
== 0 || dwCount
> JAPANESE_ERA_MAX
)
249 for (dwIndex
= 0; dwIndex
< dwCount
; dwIndex
++)
251 pEntry
= &pTable
[dwIndex
];
253 /* pEntry --> st2 --> ft2 */
254 JapaneseEra_ToSystemTime(pEntry
, &st2
);
255 SystemTimeToFileTime(&st2
, &ft2
);
258 nCompare
= CompareFileTime(&ft1
, &ft2
);