@@ -18,6 +18,7 @@ pub(crate) struct DateTimeBuilder {
1818 time : Option < time:: Time > ,
1919 weekday : Option < weekday:: Weekday > ,
2020 offset : Option < offset:: Offset > ,
21+ timezone : Option < jiff:: tz:: TimeZone > ,
2122 relative : Vec < relative:: Relative > ,
2223}
2324
@@ -33,6 +34,20 @@ impl DateTimeBuilder {
3334 self
3435 }
3536
37+ /// Sets the timezone rule for the builder.
38+ ///
39+ /// By default, the builder uses the time zone rules indicated by the `TZ`
40+ /// environment variable, or the system default rules if `TZ` is not set.
41+ /// This method allows overriding the time zone rules.
42+ fn set_timezone ( mut self , tz : jiff:: tz:: TimeZone ) -> Result < Self , & ' static str > {
43+ if self . timezone . is_some ( ) {
44+ return Err ( "timezone rule cannot appear more than once" ) ;
45+ }
46+
47+ self . timezone = Some ( tz) ;
48+ Ok ( self )
49+ }
50+
3651 /// Sets a timestamp value. Timestamp values are exclusive to other date/time
3752 /// items (date, time, weekday, timezone, relative adjustments).
3853 pub ( super ) fn set_timestamp ( mut self , ts : epoch:: Timestamp ) -> Result < Self , & ' static str > {
@@ -51,7 +66,7 @@ impl DateTimeBuilder {
5166 Ok ( self )
5267 }
5368
54- pub ( super ) fn set_date ( mut self , date : date:: Date ) -> Result < Self , & ' static str > {
69+ fn set_date ( mut self , date : date:: Date ) -> Result < Self , & ' static str > {
5570 if self . timestamp . is_some ( ) {
5671 return Err ( "timestamp cannot be combined with other date/time items" ) ;
5772 } else if self . date . is_some ( ) {
@@ -62,7 +77,7 @@ impl DateTimeBuilder {
6277 Ok ( self )
6378 }
6479
65- pub ( super ) fn set_time ( mut self , time : time:: Time ) -> Result < Self , & ' static str > {
80+ fn set_time ( mut self , time : time:: Time ) -> Result < Self , & ' static str > {
6681 if self . timestamp . is_some ( ) {
6782 return Err ( "timestamp cannot be combined with other date/time items" ) ;
6883 } else if self . time . is_some ( ) {
@@ -75,7 +90,7 @@ impl DateTimeBuilder {
7590 Ok ( self )
7691 }
7792
78- pub ( super ) fn set_weekday ( mut self , weekday : weekday:: Weekday ) -> Result < Self , & ' static str > {
93+ fn set_weekday ( mut self , weekday : weekday:: Weekday ) -> Result < Self , & ' static str > {
7994 if self . timestamp . is_some ( ) {
8095 return Err ( "timestamp cannot be combined with other date/time items" ) ;
8196 } else if self . weekday . is_some ( ) {
@@ -86,7 +101,7 @@ impl DateTimeBuilder {
86101 Ok ( self )
87102 }
88103
89- pub ( super ) fn set_offset ( mut self , timezone : offset:: Offset ) -> Result < Self , & ' static str > {
104+ fn set_offset ( mut self , timezone : offset:: Offset ) -> Result < Self , & ' static str > {
90105 if self . timestamp . is_some ( ) {
91106 return Err ( "timestamp cannot be combined with other date/time items" ) ;
92107 } else if self . offset . is_some ( )
@@ -99,10 +114,7 @@ impl DateTimeBuilder {
99114 Ok ( self )
100115 }
101116
102- pub ( super ) fn push_relative (
103- mut self ,
104- relative : relative:: Relative ,
105- ) -> Result < Self , & ' static str > {
117+ fn push_relative ( mut self , relative : relative:: Relative ) -> Result < Self , & ' static str > {
106118 if self . timestamp . is_some ( ) {
107119 return Err ( "timestamp cannot be combined with other date/time items" ) ;
108120 }
@@ -117,7 +129,7 @@ impl DateTimeBuilder {
117129 /// If a date is already set but lacks a year, the number is interpreted as
118130 /// a year. Otherwise, it's interpreted as a time in HHMM, HMM, HH, or H
119131 /// format.
120- pub ( super ) fn set_pure ( mut self , pure : String ) -> Result < Self , & ' static str > {
132+ fn set_pure ( mut self , pure : String ) -> Result < Self , & ' static str > {
121133 if self . timestamp . is_some ( ) {
122134 return Err ( "timestamp cannot be combined with other date/time items" ) ;
123135 }
@@ -149,7 +161,11 @@ impl DateTimeBuilder {
149161 }
150162
151163 pub ( super ) fn build ( self ) -> Result < Zoned , error:: Error > {
152- let base = self . base . unwrap_or ( Zoned :: now ( ) ) ;
164+ let base = self . base . unwrap_or ( if let Some ( tz) = & self . timezone {
165+ jiff:: Timestamp :: now ( ) . to_zoned ( tz. clone ( ) )
166+ } else {
167+ Zoned :: now ( )
168+ } ) ;
153169
154170 // If a timestamp is set, we use it to build the `Zoned` object.
155171 if let Some ( ts) = self . timestamp {
@@ -158,11 +174,11 @@ impl DateTimeBuilder {
158174
159175 // If any of the following items are set, we truncate the time portion
160176 // of the base date to zero; otherwise, we use the base date as is.
161- let mut dt = if self . timestamp . is_none ( )
162- && self . date . is_none ( )
177+ let mut dt = if self . date . is_none ( )
163178 && self . time . is_none ( )
164179 && self . weekday . is_none ( )
165180 && self . offset . is_none ( )
181+ && self . timezone . is_none ( )
166182 {
167183 base
168184 } else {
@@ -264,6 +280,7 @@ impl TryFrom<Vec<Item>> for DateTimeBuilder {
264280 Item :: Weekday ( weekday) => builder. set_weekday ( weekday) ?,
265281 Item :: Offset ( offset) => builder. set_offset ( offset) ?,
266282 Item :: Relative ( rel) => builder. push_relative ( rel) ?,
283+ Item :: TimeZone ( tz) => builder. set_timezone ( tz) ?,
267284 Item :: Pure ( pure) => builder. set_pure ( pure) ?,
268285 }
269286 }
0 commit comments