1- use alloc:: vec;
1+ use alloc:: { vec, vec:: Vec } ;
2+
3+ use chrono:: { DateTime , Datelike , FixedOffset , TimeZone , Timelike } ;
24
35use java_class_proto:: JavaMethodProto ;
46use jvm:: { ClassInstanceRef , Jvm , Result } ;
@@ -14,13 +16,152 @@ impl GregorianCalendar {
1416 name : "java/util/GregorianCalendar" ,
1517 parent_class : Some ( "java/util/Calendar" ) ,
1618 interfaces : vec ! [ ] ,
17- methods : vec ! [ JavaMethodProto :: new( "<init>" , "()V" , Self :: init, Default :: default ( ) ) ] ,
19+ methods : vec ! [
20+ JavaMethodProto :: new( "<init>" , "()V" , Self :: init, Default :: default ( ) ) ,
21+ JavaMethodProto :: new( "computeTime" , "()V" , Self :: compute_time, Default :: default ( ) ) ,
22+ JavaMethodProto :: new( "computeFields" , "()V" , Self :: compute_fields, Default :: default ( ) ) ,
23+ ] ,
1824 fields : vec ! [ ] ,
1925 }
2026 }
2127
22- async fn init ( _: & Jvm , _: & mut RuntimeContext , this : ClassInstanceRef < Self > ) -> Result < ( ) > {
23- tracing:: warn!( "stub java.util.GregorianCalendar::<init>({:?})" , & this) ;
28+ async fn init ( jvm : & Jvm , _: & mut RuntimeContext , this : ClassInstanceRef < Self > ) -> Result < ( ) > {
29+ tracing:: debug!( "java.util.GregorianCalendar::<init>({:?})" , & this) ;
30+
31+ let _: ( ) = jvm. invoke_special ( & this, "java/util/Calendar" , "<init>" , "()V" , ( ) ) . await ?;
32+
33+ Ok ( ( ) )
34+ }
35+
36+ async fn compute_time ( jvm : & Jvm , _: & mut RuntimeContext , mut this : ClassInstanceRef < Self > ) -> Result < ( ) > {
37+ tracing:: debug!( "java.util.GregorianCalendar::computeTime({:?})" , & this) ;
38+
39+ // fields -> time
40+
41+ let fields = jvm. get_field ( & this, "fields" , "[I" ) . await ?;
42+
43+ // TODO constant
44+ let fields: Vec < i32 > = jvm. load_array ( & fields, 0 , 17 ) . await ?;
45+ let _era = fields[ 0 ] ;
46+ let year = fields[ 1 ] ;
47+ let month = fields[ 2 ] ;
48+ let _week_of_year = fields[ 3 ] ;
49+ let _week_of_month = fields[ 4 ] ;
50+ let date = fields[ 5 ] ;
51+ let _day_of_year = fields[ 6 ] ;
52+ let _day_of_week = fields[ 7 ] ;
53+ let _day_of_week_in_month = fields[ 8 ] ;
54+ let _am_pm = fields[ 9 ] ;
55+ let _hour = fields[ 10 ] ;
56+ let hour_of_day = fields[ 11 ] ;
57+ let minute = fields[ 12 ] ;
58+ let second = fields[ 13 ] ;
59+ let millisecond = fields[ 14 ] ;
60+ let zone_offset = fields[ 15 ] ; // raw offset from GMT in milliseconds
61+ let _dst_offset = fields[ 16 ] ;
62+
63+ // TODO handle more complex cases
64+ let tz = FixedOffset :: east_opt ( zone_offset * 1000 ) . unwrap ( ) ;
65+ let timestamp = tz
66+ . with_ymd_and_hms ( year, ( month + 1 ) as _ , date as _ , hour_of_day as _ , minute as _ , second as _ )
67+ . unwrap ( )
68+ . timestamp_millis ( ) as i64 ;
69+
70+ let calculated_time = timestamp + millisecond as i64 ;
71+
72+ jvm. put_field ( & mut this, "time" , "J" , calculated_time) . await ?;
73+
74+ Ok ( ( ) )
75+ }
76+
77+ async fn compute_fields ( jvm : & Jvm , _: & mut RuntimeContext , this : ClassInstanceRef < Self > ) -> Result < ( ) > {
78+ tracing:: debug!( "java.util.GregorianCalendar::computeFields({:?})" , & this) ;
79+
80+ // time -> fields
81+
82+ let time: i64 = jvm. get_field ( & this, "time" , "J" ) . await ?;
83+ let date_time = DateTime :: from_timestamp_millis ( time as _ ) . unwrap ( ) ;
84+
85+ let calculated_fields = vec ! [
86+ 1 , // CE
87+ date_time. year( ) ,
88+ date_time. month( ) as i32 - 1 ,
89+ date_time. iso_week( ) . week( ) as _,
90+ ( date_time. day( ) / 7 ) as _, // TODO correctly get
91+ date_time. day( ) as _,
92+ date_time. ordinal( ) as _,
93+ date_time. weekday( ) . number_from_monday( ) as _,
94+ ( date_time. day( ) % 7 ) as _, // TODO correctly get
95+ ( date_time. hour( ) / 12 ) as _,
96+ ( date_time. hour( ) % 12 ) as _,
97+ date_time. hour( ) as _,
98+ date_time. minute( ) as _,
99+ date_time. second( ) as _,
100+ ( date_time. nanosecond( ) / 1_000_000 ) as _,
101+ 0 ,
102+ 0 ,
103+ ] ;
104+
105+ let mut fields = jvm. get_field ( & this, "fields" , "[I" ) . await ?;
106+ jvm. store_array ( & mut fields, 0 , calculated_fields) . await ?;
107+
108+ Ok ( ( ) )
109+ }
110+ }
111+
112+ #[ cfg( test) ]
113+ mod test {
114+ use jvm:: Result ;
115+
116+ use crate :: test:: test_jvm;
117+
118+ #[ tokio:: test]
119+ async fn test_gregorian_calendar ( ) -> Result < ( ) > {
120+ let jvm = test_jvm ( ) . await ?;
121+
122+ let timestamp = 0i64 ;
123+ let calendar = jvm
124+ . invoke_static ( "java/util/Calendar" , "getInstance" , "()Ljava/util/Calendar;" , ( ) )
125+ . await ?;
126+ let date = jvm. new_class ( "java/util/Date" , "(J)V" , ( timestamp, ) ) . await ?;
127+
128+ let _: ( ) = jvm. invoke_virtual ( & calendar, "setTime" , "(Ljava/util/Date;)V" , ( date, ) ) . await ?;
129+ let year: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 1 , ) ) . await ?;
130+ assert_eq ! ( 1970 , year) ;
131+
132+ let month: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 2 , ) ) . await ?;
133+ assert_eq ! ( 0 , month) ;
134+
135+ let day: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 5 , ) ) . await ?;
136+ assert_eq ! ( 1 , day) ;
137+
138+ let timestamp = 737521516000i64 ;
139+ let date = jvm. new_class ( "java/util/Date" , "(J)V" , ( timestamp, ) ) . await ?;
140+
141+ let _: ( ) = jvm. invoke_virtual ( & calendar, "setTime" , "(Ljava/util/Date;)V" , ( date, ) ) . await ?;
142+
143+ let year: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 1 , ) ) . await ?;
144+ assert_eq ! ( 1993 , year) ;
145+
146+ let month: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 2 , ) ) . await ?;
147+ assert_eq ! ( 4 , month) ;
148+
149+ let day: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 5 , ) ) . await ?;
150+ assert_eq ! ( 16 , day) ;
151+
152+ let hour: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 11 , ) ) . await ?;
153+ assert_eq ! ( 3 , hour) ;
154+
155+ let minute: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 12 , ) ) . await ?;
156+ assert_eq ! ( 5 , minute) ;
157+
158+ let second: i32 = jvm. invoke_virtual ( & calendar, "get" , "(I)I" , ( 13 , ) ) . await ?;
159+ assert_eq ! ( 16 , second) ;
160+
161+ let _: ( ) = jvm. invoke_virtual ( & calendar, "set" , "(II)V" , ( 1 , 1999 ) ) . await ?;
162+ let date = jvm. invoke_virtual ( & calendar, "getTime" , "()Ljava/util/Date;" , ( ) ) . await ?;
163+ let timestamp: i64 = jvm. invoke_virtual ( & date, "getTime" , "()J" , ( ) ) . await ?;
164+ assert_eq ! ( 926823916000 , timestamp) ;
24165
25166 Ok ( ( ) )
26167 }
0 commit comments