@@ -8,6 +8,9 @@ use std::{cmp::Ordering, fmt, str};
8
8
use super :: rule:: { AlternateTime , TransitionRule } ;
9
9
use super :: { parser, Error , DAYS_PER_WEEK , SECONDS_PER_DAY } ;
10
10
11
+ #[ cfg( target_env = "ohos" ) ]
12
+ use crate :: offset:: local:: tz_info:: parser:: Cursor ;
13
+
11
14
/// Time zone
12
15
#[ derive( Debug , Clone , Eq , PartialEq ) ]
13
16
pub ( crate ) struct TimeZone {
@@ -50,6 +53,12 @@ impl TimeZone {
50
53
}
51
54
}
52
55
56
+ // ohos merge all file into tzdata since ver35
57
+ #[ cfg( target_env = "ohos" ) ]
58
+ {
59
+ return Self :: from_tz_data ( & find_ohos_tz_data ( tz_string) ?) ;
60
+ }
61
+
53
62
let mut chars = tz_string. chars ( ) ;
54
63
if chars. next ( ) == Some ( ':' ) {
55
64
return Self :: from_file ( & mut find_tz_file ( chars. as_str ( ) ) ?) ;
@@ -629,6 +638,58 @@ fn find_tz_file(path: impl AsRef<Path>) -> Result<File, Error> {
629
638
}
630
639
}
631
640
641
+ #[ cfg( target_env = "ohos" ) ]
642
+ fn from_tzdata_bytes ( bytes : & mut Vec < u8 > , tz_string : & str ) -> Result < Vec < u8 > , Error > {
643
+ const VERSION_SIZE : usize = 12 ;
644
+ const OFFSET_SIZE : usize = 4 ;
645
+ const INDEX_CHUNK_SIZE : usize = 48 ;
646
+ const ZONENAME_SIZE : usize = 40 ;
647
+
648
+ let mut cursor = Cursor :: new ( & bytes) ;
649
+ // version head
650
+ let _ = cursor. read_exact ( VERSION_SIZE ) ?;
651
+ let index_offset_offset = cursor. read_be_u32 ( ) ?;
652
+ let data_offset_offset = cursor. read_be_u32 ( ) ?;
653
+ // final offset
654
+ let _ = cursor. read_be_u32 ( ) ?;
655
+
656
+ cursor. seek_after ( index_offset_offset as usize ) ?;
657
+ let mut idx = index_offset_offset;
658
+ while idx < data_offset_offset {
659
+ let index_buf = cursor. read_exact ( ZONENAME_SIZE ) ?;
660
+ let offset = cursor. read_be_u32 ( ) ?;
661
+ let length = cursor. read_be_u32 ( ) ?;
662
+ let zone_name = str:: from_utf8 ( index_buf) ?. trim_end_matches ( '\0' ) ;
663
+ if zone_name != tz_string {
664
+ idx += INDEX_CHUNK_SIZE as u32 ;
665
+ continue ;
666
+ }
667
+ cursor. seek_after ( ( data_offset_offset + offset) as usize ) ?;
668
+ return match cursor. read_exact ( length as usize ) {
669
+ Ok ( result) => Ok ( result. to_vec ( ) ) ,
670
+ Err ( _err) => Err ( Error :: InvalidTzFile ( "invalid ohos tzdata chunk" ) ) ,
671
+ } ;
672
+ }
673
+
674
+ Err ( Error :: InvalidTzString ( "cannot find tz string within tzdata" ) )
675
+ }
676
+
677
+ #[ cfg( target_env = "ohos" ) ]
678
+ fn from_tzdata_file ( file : & mut File , tz_string : & str ) -> Result < Vec < u8 > , Error > {
679
+ let mut bytes = Vec :: new ( ) ;
680
+ file. read_to_end ( & mut bytes) ?;
681
+ from_tzdata_bytes ( & mut bytes, tz_string)
682
+ }
683
+
684
+ #[ cfg( target_env = "ohos" ) ]
685
+ fn find_ohos_tz_data ( tz_string : & str ) -> Result < Vec < u8 > , Error > {
686
+ const TZDATA_PATH : & str = "/system/etc/zoneinfo/tzdata" ;
687
+ match File :: open ( TZDATA_PATH ) {
688
+ Ok ( mut file) => from_tzdata_file ( & mut file, tz_string) ,
689
+ Err ( err) => Err ( err. into ( ) ) ,
690
+ }
691
+ }
692
+
632
693
// Possible system timezone directories
633
694
#[ cfg( unix) ]
634
695
const ZONE_INFO_DIRECTORIES : [ & str ; 4 ] =
0 commit comments