@@ -8,10 +8,12 @@ use crate::cal::abstract_gregorian::{
88use crate :: cal:: gregorian:: CeBce ;
99use crate :: calendar_arithmetic:: ArithmeticDate ;
1010use crate :: error:: { DateError , UnknownEraError } ;
11- use crate :: provider:: { CalendarJapaneseExtendedV1 , CalendarJapaneseModernV1 , EraStartDate } ;
11+ use crate :: provider:: {
12+ CalendarJapaneseExtendedV1 , CalendarJapaneseModernV1 , EraStartDate , PackedEra ,
13+ } ;
1214use crate :: { types, AsCalendar , Date } ;
1315use icu_provider:: prelude:: * ;
14- use tinystr:: tinystr;
16+ use tinystr:: { tinystr, TinyAsciiStr } ;
1517
1618/// The [Japanese Calendar] (with modern eras only)
1719///
@@ -39,9 +41,17 @@ use tinystr::tinystr;
3941///
4042/// These eras are loaded from data, requiring a data provider capable of providing [`CalendarJapaneseModernV1`]
4143/// data.
42- #[ derive( Clone , Debug , Default ) ]
44+ #[ derive( Clone , Debug , Copy ) ]
4345pub struct Japanese {
44- eras : DataPayload < CalendarJapaneseModernV1 > ,
46+ last_era : PackedEra ,
47+ }
48+
49+ impl Default for Japanese {
50+ fn default ( ) -> Self {
51+ Self {
52+ last_era : PackedEra :: pack ( REIWA ) ,
53+ }
54+ }
4555}
4656
4757/// The [Japanese Calendar] (with historical eras)
@@ -86,9 +96,7 @@ impl Japanese {
8696 #[ cfg( feature = "compiled_data" ) ]
8797 pub const fn new ( ) -> Self {
8898 Self {
89- eras : DataPayload :: from_static_ref (
90- crate :: provider:: Baked :: SINGLETON_CALENDAR_JAPANESE_MODERN_V1 ,
91- ) ,
99+ last_era : * crate :: provider:: Baked :: SINGLETON_CALENDAR_JAPANESE_MODERN_V1 ,
92100 }
93101 }
94102
@@ -105,7 +113,7 @@ impl Japanese {
105113 provider : & D ,
106114 ) -> Result < Self , DataError > {
107115 Ok ( Self {
108- eras : provider. load ( Default :: default ( ) ) ?. payload ,
116+ last_era : * provider. load ( Default :: default ( ) ) ?. payload . get ( ) ,
109117 } )
110118 }
111119}
@@ -143,31 +151,46 @@ impl JapaneseExtended {
143151 }
144152}
145153
146- const MEIJI_START : EraStartDate = EraStartDate {
147- year : 1868 ,
148- month : 10 ,
149- day : 23 ,
150- } ;
151- const TAISHO_START : EraStartDate = EraStartDate {
152- year : 1912 ,
153- month : 7 ,
154- day : 30 ,
155- } ;
156- const SHOWA_START : EraStartDate = EraStartDate {
157- year : 1926 ,
158- month : 12 ,
159- day : 25 ,
160- } ;
161- const HEISEI_START : EraStartDate = EraStartDate {
162- year : 1989 ,
163- month : 1 ,
164- day : 8 ,
165- } ;
166- const REIWA_START : EraStartDate = EraStartDate {
167- year : 2019 ,
168- month : 5 ,
169- day : 1 ,
170- } ;
154+ const MEIJI : ( EraStartDate , TinyAsciiStr < 16 > ) = (
155+ EraStartDate {
156+ year : 1868 ,
157+ month : 10 ,
158+ day : 23 ,
159+ } ,
160+ tinystr ! ( 16 , "meiji" ) ,
161+ ) ;
162+ const TAISHO : ( EraStartDate , TinyAsciiStr < 16 > ) = (
163+ EraStartDate {
164+ year : 1912 ,
165+ month : 7 ,
166+ day : 30 ,
167+ } ,
168+ tinystr ! ( 16 , "taisho" ) ,
169+ ) ;
170+ const SHOWA : ( EraStartDate , TinyAsciiStr < 16 > ) = (
171+ EraStartDate {
172+ year : 1926 ,
173+ month : 12 ,
174+ day : 25 ,
175+ } ,
176+ tinystr ! ( 16 , "showa" ) ,
177+ ) ;
178+ const HEISEI : ( EraStartDate , TinyAsciiStr < 16 > ) = (
179+ EraStartDate {
180+ year : 1989 ,
181+ month : 1 ,
182+ day : 8 ,
183+ } ,
184+ tinystr ! ( 16 , "heisei" ) ,
185+ ) ;
186+ pub ( crate ) const REIWA : ( EraStartDate , TinyAsciiStr < 16 > ) = (
187+ EraStartDate {
188+ year : 2019 ,
189+ month : 5 ,
190+ day : 1 ,
191+ } ,
192+ tinystr ! ( 16 , "reiwa" ) ,
193+ ) ;
171194
172195impl GregorianYears for & ' _ Japanese {
173196 fn extended_from_era_year (
@@ -178,80 +201,36 @@ impl GregorianYears for &'_ Japanese {
178201 if let Ok ( g) = CeBce . extended_from_era_year ( era, year) {
179202 return Ok ( g) ;
180203 }
181- let Some ( era) = era else {
182- // unreachable, handled by CeBce
183- return Err ( UnknownEraError ) ;
184- } ;
185-
186- // Avoid linear search by trying well known eras
187- if era == b"reiwa" {
188- return Ok ( year - 1 + REIWA_START . year ) ;
189- } else if era == b"heisei" {
190- return Ok ( year - 1 + HEISEI_START . year ) ;
191- } else if era == b"showa" {
192- return Ok ( year - 1 + SHOWA_START . year ) ;
193- } else if era == b"taisho" {
194- return Ok ( year - 1 + TAISHO_START . year ) ;
195- } else if era == b"meiji" {
196- return Ok ( year - 1 + MEIJI_START . year ) ;
197- }
198204
199- let era_start = self
200- . eras
201- . get ( )
202- . dates_to_eras
203- . iter ( )
204- . rev ( )
205- . find_map ( |( s, e) | ( e. as_bytes ( ) == era) . then_some ( s) )
205+ let ( start, _) = [ self . last_era . unpack ( ) , REIWA , HEISEI , SHOWA , TAISHO , MEIJI ]
206+ . into_iter ( )
207+ . find ( |( _, name) | era == Some ( name. as_bytes ( ) ) )
206208 . ok_or ( UnknownEraError ) ?;
207- Ok ( era_start. year + year - 1 )
209+
210+ Ok ( year - 1 + start. year )
208211 }
209212
210213 fn era_year_from_extended ( & self , year : i32 , month : u8 , day : u8 ) -> types:: EraYear {
211214 let date: EraStartDate = EraStartDate { year, month, day } ;
212215
213- let ( start, era) = if date >= MEIJI_START
214- && self
215- . eras
216- . get ( )
217- . dates_to_eras
218- . last ( )
219- . is_some_and ( |( _, e) | e == tinystr ! ( 16 , "reiwa" ) )
216+ if let Some ( ( start, era) ) = [ self . last_era . unpack ( ) , REIWA , HEISEI , SHOWA , TAISHO , MEIJI ]
217+ . into_iter ( )
218+ . find ( |& ( start, _) | date >= start)
220219 {
221- // We optimize for the five "modern" post-Meiji eras, which are stored in a smaller
222- // array and also hardcoded. The hardcoded version is not used if data indicates the
223- // presence of newer eras.
224- if date >= REIWA_START {
225- ( REIWA_START , tinystr ! ( 16 , "reiwa" ) )
226- } else if date >= HEISEI_START {
227- ( HEISEI_START , tinystr ! ( 16 , "heisei" ) )
228- } else if date >= SHOWA_START {
229- ( SHOWA_START , tinystr ! ( 16 , "showa" ) )
230- } else if date >= TAISHO_START {
231- ( TAISHO_START , tinystr ! ( 16 , "taisho" ) )
232- } else {
233- ( MEIJI_START , tinystr ! ( 16 , "meiji" ) )
220+ types:: EraYear {
221+ era,
222+ // TODO: return era indices?
223+ era_index : None ,
224+ year : year - start. year + 1 ,
225+ extended_year : year,
226+ ambiguity : types:: YearAmbiguity :: CenturyRequired ,
234227 }
235228 } else {
236- let data = & self . eras . get ( ) . dates_to_eras ;
237- match data. iter ( ) . rfind ( |& ( s, _) | date >= s) {
238- None => {
239- return types:: EraYear {
240- // TODO: return era indices?
241- era_index : None ,
242- ..CeBce . era_year_from_extended ( year, month, day)
243- } ;
244- }
245- Some ( ( s, e) ) => ( s, e) ,
229+ types:: EraYear {
230+ // TODO: return era indices?
231+ era_index : None ,
232+ ..CeBce . era_year_from_extended ( year, month, day)
246233 }
247- } ;
248-
249- types:: EraYear {
250- era,
251- era_index : None ,
252- year : year - start. year + 1 ,
253- extended_year : year,
254- ambiguity : types:: YearAmbiguity :: CenturyRequired ,
255234 }
256235 }
257236
@@ -281,16 +260,16 @@ impl GregorianYears for &'_ JapaneseExtended {
281260 } ;
282261
283262 // Avoid linear search by trying well known eras
284- if era == b"reiwa" {
285- return Ok ( year - 1 + REIWA_START . year ) ;
286- } else if era == b"heisei" {
287- return Ok ( year - 1 + HEISEI_START . year ) ;
288- } else if era == b"showa" {
289- return Ok ( year - 1 + SHOWA_START . year ) ;
290- } else if era == b"taisho" {
291- return Ok ( year - 1 + TAISHO_START . year ) ;
292- } else if era == b"meiji" {
293- return Ok ( year - 1 + MEIJI_START . year ) ;
263+ if era == REIWA . 1 . as_bytes ( ) {
264+ return Ok ( year - 1 + REIWA . 0 . year ) ;
265+ } else if era == HEISEI . 1 . as_bytes ( ) {
266+ return Ok ( year - 1 + HEISEI . 0 . year ) ;
267+ } else if era == SHOWA . 1 . as_bytes ( ) {
268+ return Ok ( year - 1 + SHOWA . 0 . year ) ;
269+ } else if era == TAISHO . 1 . as_bytes ( ) {
270+ return Ok ( year - 1 + TAISHO . 0 . year ) ;
271+ } else if era == MEIJI . 1 . as_bytes ( ) {
272+ return Ok ( year - 1 + MEIJI . 0 . year ) ;
294273 }
295274
296275 let data = & self . eras . get ( ) . dates_to_eras ;
@@ -324,7 +303,7 @@ impl GregorianYears for &'_ JapaneseExtended {
324303 fn era_year_from_extended ( & self , year : i32 , month : u8 , day : u8 ) -> types:: EraYear {
325304 let date: EraStartDate = EraStartDate { year, month, day } ;
326305
327- let ( start, era) = if date >= MEIJI_START
306+ let ( start, era) = if date >= MEIJI . 0
328307 && self
329308 . eras
330309 . get ( )
@@ -335,16 +314,16 @@ impl GregorianYears for &'_ JapaneseExtended {
335314 // We optimize for the five "modern" post-Meiji eras, which are stored in a smaller
336315 // array and also hardcoded. The hardcoded version is not used if data indicates the
337316 // presence of newer eras.
338- if date >= REIWA_START {
339- ( REIWA_START , tinystr ! ( 16 , "reiwa" ) )
340- } else if date >= HEISEI_START {
341- ( HEISEI_START , tinystr ! ( 16 , "heisei" ) )
342- } else if date >= SHOWA_START {
343- ( SHOWA_START , tinystr ! ( 16 , "showa" ) )
344- } else if date >= TAISHO_START {
345- ( TAISHO_START , tinystr ! ( 16 , "taisho" ) )
317+ if date >= REIWA . 0 {
318+ REIWA
319+ } else if date >= HEISEI . 0 {
320+ HEISEI
321+ } else if date >= SHOWA . 0 {
322+ SHOWA
323+ } else if date >= TAISHO . 0 {
324+ TAISHO
346325 } else {
347- ( MEIJI_START , tinystr ! ( 16 , "meiji" ) )
326+ MEIJI
348327 }
349328 } else {
350329 let data = & self . eras . get ( ) . dates_to_eras ;
@@ -616,6 +595,13 @@ mod tests {
616595 )
617596 }
618597
598+ #[ test]
599+ #[ ignore]
600+ fn sizes ( ) {
601+ assert_eq ! ( core:: mem:: size_of:: <Japanese >( ) , 11 ) ;
602+ assert_eq ! ( core:: mem:: size_of:: <JapaneseExtended >( ) , 32 ) ;
603+ }
604+
619605 #[ test]
620606 fn test_japanese ( ) {
621607 let calendar = Japanese :: new ( ) ;
0 commit comments