Skip to content

Commit

Permalink
Replace datetime and zoneinfo_compiled crates with chrono
Browse files Browse the repository at this point in the history
- Improve compatibility with other OSes, timezone are handled for us
- Reduce significantly code handling and rendering time
  • Loading branch information
ariasuni committed Mar 18, 2022
1 parent b869bd0 commit 0f14532
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 294 deletions.
82 changes: 43 additions & 39 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 4 additions & 10 deletions Cargo.toml
Expand Up @@ -18,6 +18,7 @@ name = "exa"

[dependencies]
ansi_term = "0.12"
chrono = "0.4"
glob = "0.3"
lazy_static = "1.3"
libc = "0.2"
Expand All @@ -31,27 +32,20 @@ term_grid = "0.2.0"
terminal_size = "0.1.16"
unicode-width = "0.1"
users = "0.11"
zoneinfo_compiled = "0.5.1"

[dependencies.datetime]
version = "0.5.2"
default-features = false
features = ["format"]

[dependencies.git2]
version = "0.13"
optional = true
default-features = false

[build-dependencies.datetime]
version = "0.5.2"
default-features = false

[features]
default = [ "git" ]
git = [ "git2" ]
vendored-openssl = ["git2/vendored-openssl"]

[build-dependencies]
chrono = "0.4"


# make dev builds faster by excluding debug symbols
[profile.dev]
Expand Down
6 changes: 3 additions & 3 deletions build.rs
Expand Up @@ -15,7 +15,7 @@ use std::fs::File;
use std::io::{self, Write};
use std::path::PathBuf;

use datetime::{LocalDateTime, ISO};
use chrono::prelude::*;


/// The build script entry point.
Expand Down Expand Up @@ -118,6 +118,6 @@ fn nonstandard_features_string() -> String {

/// Formats the current date as an ISO 8601 string.
fn build_date() -> String {
let now = LocalDateTime::now();
format!("{}", now.date().iso())
let now = Local::now();
now.date().format("%Y-%m-%d").to_string()
}
36 changes: 13 additions & 23 deletions src/fs/file.rs
Expand Up @@ -3,7 +3,8 @@
use std::io;
use std::os::unix::fs::{FileTypeExt, MetadataExt, PermissionsExt};
use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use chrono::prelude::*;

use log::*;

Expand Down Expand Up @@ -336,37 +337,26 @@ impl<'dir> File<'dir> {
}

/// This file’s last modified timestamp, if available on this platform.
pub fn modified_time(&self) -> Option<SystemTime> {
self.metadata.modified().ok()
pub fn modified_time(&self) -> Option<NaiveDateTime> {
self.metadata.modified().map(|st| DateTime::<Utc>::from(st).naive_utc()).ok()
}

/// This file’s last changed timestamp, if available on this platform.
pub fn changed_time(&self) -> Option<SystemTime> {
let (mut sec, mut nanosec) = (self.metadata.ctime(), self.metadata.ctime_nsec());

if sec < 0 {
if nanosec > 0 {
sec += 1;
nanosec -= 1_000_000_000;
}

let duration = Duration::new(sec.abs() as u64, nanosec.abs() as u32);
Some(UNIX_EPOCH - duration)
}
else {
let duration = Duration::new(sec as u64, nanosec as u32);
Some(UNIX_EPOCH + duration)
}
pub fn changed_time(&self) -> Option<NaiveDateTime> {
Some(NaiveDateTime::from_timestamp(
self.metadata.ctime(),
self.metadata.ctime_nsec() as u32,
))
}

/// This file’s last accessed timestamp, if available on this platform.
pub fn accessed_time(&self) -> Option<SystemTime> {
self.metadata.accessed().ok()
pub fn accessed_time(&self) -> Option<NaiveDateTime> {
self.metadata.accessed().map(|st| DateTime::<Utc>::from(st).naive_utc()).ok()
}

/// This file’s created timestamp, if available on this platform.
pub fn created_time(&self) -> Option<SystemTime> {
self.metadata.created().ok()
pub fn created_time(&self) -> Option<NaiveDateTime> {
self.metadata.created().map(|st| DateTime::<Utc>::from(st).naive_utc()).ok()
}

/// This file’s ‘type’.
Expand Down
24 changes: 8 additions & 16 deletions src/output/render/times.rs
@@ -1,27 +1,19 @@
use std::time::SystemTime;

use datetime::TimeZone;
use ansi_term::Style;

use crate::output::cell::TextCell;
use crate::output::time::TimeFormat;

use ansi_term::Style;
use chrono::prelude::*;


pub trait Render {
fn render(self, style: Style, tz: &Option<TimeZone>, format: TimeFormat) -> TextCell;
fn render(self, style: Style, time_offset: FixedOffset, time_format: TimeFormat) -> TextCell;
}

impl Render for Option<SystemTime> {
fn render(self, style: Style, tz: &Option<TimeZone>, format: TimeFormat) -> TextCell {
impl Render for Option<NaiveDateTime> {
fn render(self, style: Style, time_offset: FixedOffset, time_format: TimeFormat) -> TextCell {
let datestamp = if let Some(time) = self {
if let Some(ref tz) = tz {
format.format_zoned(time, tz)
}
else {
format.format_local(time)
}
}
else {
time_format.format(&DateTime::<FixedOffset>::from_utc(time, time_offset))
} else {
String::from("-")
};

Expand Down
51 changes: 10 additions & 41 deletions src/output/table.rs
@@ -1,10 +1,8 @@
use std::cmp::max;
use std::env;
use std::ops::Deref;
use std::sync::{Mutex, MutexGuard};

use datetime::TimeZone;
use zoneinfo_compiled::{CompiledData, Result as TZResult};
use chrono::prelude::*;

use lazy_static::lazy_static;
use log::*;
Expand Down Expand Up @@ -266,13 +264,12 @@ impl Default for TimeTypes {
/// Any environment field should be able to be mocked up for test runs.
pub struct Environment {

/// The computer’s current time offset, determined from time zone.
time_offset: FixedOffset,

/// Localisation rules for formatting numbers.
numeric: locale::Numeric,

/// The computer’s current time zone. This gets used to determine how to
/// offset files’ timestamps.
tz: Option<TimeZone>,

/// Mapping cache of user IDs to usernames.
users: Mutex<UsersCache>,
}
Expand All @@ -283,42 +280,14 @@ impl Environment {
}

fn load_all() -> Self {
let tz = match determine_time_zone() {
Ok(t) => {
Some(t)
}
Err(ref e) => {
println!("Unable to determine time zone: {}", e);
None
}
};
let time_offset = *Local::now().offset();

let numeric = locale::Numeric::load_user_locale()
.unwrap_or_else(|_| locale::Numeric::english());

let users = Mutex::new(UsersCache::new());

Self { numeric, tz, users }
}
}

fn determine_time_zone() -> TZResult<TimeZone> {
if let Ok(file) = env::var("TZ") {
TimeZone::from_file({
if file.starts_with('/') {
file
} else {
format!("/usr/share/zoneinfo/{}", {
if file.starts_with(':') {
file.replacen(":", "", 1)
} else {
file
}
})
}
})
} else {
TimeZone::from_file("/etc/localtime")
Self { time_offset, numeric, users }
}
}

Expand Down Expand Up @@ -430,16 +399,16 @@ impl<'a, 'f> Table<'a> {
}

Column::Timestamp(TimeType::Modified) => {
file.modified_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
file.modified_time().render(self.theme.ui.date, self.env.time_offset, self.time_format)
}
Column::Timestamp(TimeType::Changed) => {
file.changed_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
file.changed_time().render(self.theme.ui.date, self.env.time_offset, self.time_format)
}
Column::Timestamp(TimeType::Created) => {
file.created_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
file.created_time().render(self.theme.ui.date, self.env.time_offset, self.time_format)
}
Column::Timestamp(TimeType::Accessed) => {
file.accessed_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
file.accessed_time().render(self.theme.ui.date, self.env.time_offset, self.time_format)
}
}
}
Expand Down

0 comments on commit 0f14532

Please sign in to comment.