Skip to content

Commit

Permalink
allow sharing of the allocated environment variable
Browse files Browse the repository at this point in the history
  • Loading branch information
esheppa authored and djc committed Nov 11, 2022
1 parent 84f3c30 commit 57908e9
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 15 deletions.
11 changes: 5 additions & 6 deletions src/offset/local/tz_info/timezone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ impl TimeZone {
///
/// This method in not supported on non-UNIX platforms, and returns the UTC time zone instead.
///
pub(crate) fn local() -> Result<Self, Error> {
if let Ok(tz) = std::env::var("TZ") {
Self::from_posix_tz(&tz)
} else {
Self::from_posix_tz("localtime")
pub(crate) fn local(env_tz: Option<&str>) -> Result<Self, Error> {
match env_tz {
Some(tz) => Self::from_posix_tz(tz),
None => Self::from_posix_tz("localtime"),
}
}

Expand Down Expand Up @@ -813,7 +812,7 @@ mod tests {
// so just ensure that ::local() acts as expected
// in this case
if let Ok(tz) = std::env::var("TZ") {
let time_zone_local = TimeZone::local()?;
let time_zone_local = TimeZone::local(Some(tz.as_str()))?;
let time_zone_local_1 = TimeZone::from_posix_tz(&tz)?;
assert_eq!(time_zone_local, time_zone_local_1);
}
Expand Down
29 changes: 20 additions & 9 deletions src/offset/local/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ enum Source {
Environment,
}

impl Default for Source {
fn default() -> Source {
impl Source {
fn new(env_tz: Option<&str>) -> Source {
// use of var_os avoids allocating, which is nice
// as we are only going to discard the string anyway
// but we must ensure the contents are valid unicode
// otherwise the behaivour here would be different
// to that in `naive_to_local`
match env::var_os("TZ") {
Some(ref s) if s.to_str().is_some() => Source::Environment,
Some(_) | None => match fs::symlink_metadata("/etc/localtime") {
match env_tz {
Some(_) => Source::Environment,
None => match fs::symlink_metadata("/etc/localtime") {
Ok(data) => Source::LocalTime {
// we have to pick a sensible default when the mtime fails
// by picking SystemTime::now() we raise the probability of
Expand Down Expand Up @@ -89,14 +89,20 @@ fn fallback_timezone() -> Option<TimeZone> {
impl Default for Cache {
fn default() -> Cache {
// default to UTC if no local timezone can be found
let env_tz = env::var("TZ").ok();
let env_ref = env_tz.as_ref().map(|s| s.as_str());
Cache {
zone: TimeZone::local().ok().or_else(fallback_timezone).unwrap_or_else(TimeZone::utc),
source: Source::default(),
last_checked: SystemTime::now(),
source: Source::new(env_ref),
zone: current_zone(env_ref),
}
}
}

fn current_zone(var: Option<&str>) -> TimeZone {
TimeZone::local(var).ok().or_else(fallback_timezone).unwrap_or_else(TimeZone::utc)
}

impl Cache {
fn offset(&mut self, d: NaiveDateTime, local: bool) -> LocalResult<DateTime<Local>> {
let now = SystemTime::now();
Expand All @@ -109,7 +115,9 @@ impl Cache {
// user's perspective.
Ok(d) if d.as_secs() < 1 => (),
Ok(_) | Err(_) => {
let new_source = Source::default();
let env_tz = env::var("TZ").ok();
let env_ref = env_tz.as_ref().map(|s| s.as_str());
let new_source = Source::new(env_ref);

let out_of_date = match (&self.source, &new_source) {
// change from env to file or file to env, must recreate the zone
Expand All @@ -126,8 +134,11 @@ impl Cache {
};

if out_of_date {
*self = Cache::default();
self.zone = current_zone(env_ref);
}

self.last_checked = now;
self.source = new_source;
}
}

Expand Down

0 comments on commit 57908e9

Please sign in to comment.