@@ -8,6 +8,9 @@ use std::{cmp::Ordering, fmt, str};
88use super :: rule:: { AlternateTime , TransitionRule } ;
99use super :: { parser, Error , DAYS_PER_WEEK , SECONDS_PER_DAY } ;
1010
11+ #[ cfg( target_env = "ohos" ) ]
12+ use crate :: offset:: local:: tz_info:: parser:: Cursor ;
13+
1114/// Time zone
1215#[ derive( Debug , Clone , Eq , PartialEq ) ]
1316pub ( crate ) struct TimeZone {
@@ -50,6 +53,14 @@ impl TimeZone {
5053 }
5154 }
5255
56+ // ohos merge all file into tzdata since ver35
57+ #[ cfg( target_env = "ohos" ) ]
58+ {
59+ if let Ok ( bytes) = find_ohos_tz_data ( tz_string) {
60+ return Self :: from_tz_data ( & bytes) ;
61+ }
62+ }
63+
5364 let mut chars = tz_string. chars ( ) ;
5465 if chars. next ( ) == Some ( ':' ) {
5566 return Self :: from_file ( & mut find_tz_file ( chars. as_str ( ) ) ?) ;
@@ -629,6 +640,63 @@ fn find_tz_file(path: impl AsRef<Path>) -> Result<File, Error> {
629640 }
630641}
631642
643+ #[ cfg( target_env = "ohos" ) ]
644+ const TZDATA_PATH : & str = "/system/etc/zoneinfo/tzdata" ;
645+
646+ #[ cfg( target_env = "ohos" ) ]
647+ fn from_tzdata_bytes ( bytes : & mut Vec < u8 > , tz_string : & str ) -> Result < Vec < u8 > , Error > {
648+ const VERSION_SIZE : usize = 12 ;
649+ const OFFSET_SIZE : usize = 4 ;
650+ const INDEX_CHUNK_SIZE : usize = 48 ;
651+ const ZONENAME_SIZE : usize = 40 ;
652+
653+ let mut cursor = Cursor :: new ( & bytes) ;
654+ // version head
655+ let _ = cursor. read_exact ( VERSION_SIZE ) ?;
656+ let index_offset_offset = cursor. read_be_u32 ( ) ?;
657+ let data_offset_offset = cursor. read_be_u32 ( ) ?;
658+ // final offset
659+ let _ = cursor. read_be_u32 ( ) ?;
660+
661+ if cursor. seek_after ( index_offset_offset as usize ) . is_err ( ) {
662+ return Err ( Error :: Io ( io:: ErrorKind :: NotFound . into ( ) ) ) ;
663+ }
664+ let mut idx = index_offset_offset;
665+ while idx < data_offset_offset {
666+ let index_buf = cursor. read_exact ( ZONENAME_SIZE ) ?;
667+ let offset = cursor. read_be_u32 ( ) ?;
668+ let length = cursor. read_be_u32 ( ) ?;
669+ let zone_name = str:: from_utf8 ( index_buf) ?. trim_end_matches ( '\0' ) ;
670+ if zone_name == tz_string {
671+ if cursor. seek_after ( ( data_offset_offset + offset) as usize ) . is_err ( ) {
672+ return Err ( Error :: Io ( io:: ErrorKind :: NotFound . into ( ) ) ) ;
673+ }
674+ return match cursor. read_exact ( length as usize ) {
675+ Ok ( result) => Ok ( result. to_vec ( ) ) ,
676+ _ => Err ( Error :: Io ( io:: ErrorKind :: NotFound . into ( ) ) ) ,
677+ } ;
678+ }
679+ idx += INDEX_CHUNK_SIZE as u32 ;
680+ }
681+
682+ Err ( Error :: Io ( io:: ErrorKind :: NotFound . into ( ) ) )
683+ }
684+
685+ #[ cfg( target_env = "ohos" ) ]
686+ fn from_tzdata_file ( file : & mut File , tz_string : & str ) -> Result < Vec < u8 > , Error > {
687+ let mut bytes: Vec < u8 > = Vec :: new ( ) ;
688+ file. read_to_end ( & mut bytes) ?;
689+ from_tzdata_bytes ( & mut bytes, tz_string)
690+ }
691+
692+ #[ cfg( target_env = "ohos" ) ]
693+ fn find_ohos_tz_data ( tz_string : & str ) -> Result < Vec < u8 > , Error > {
694+ if let Ok ( mut file) = File :: open ( TZDATA_PATH ) {
695+ return from_tzdata_file ( & mut file, tz_string) ;
696+ }
697+ Err ( Error :: Io ( io:: ErrorKind :: NotFound . into ( ) ) )
698+ }
699+
632700// Possible system timezone directories
633701#[ cfg( unix) ]
634702const ZONE_INFO_DIRECTORIES : [ & str ; 4 ] =
0 commit comments