2017-08-09 16:14:16 +00:00
|
|
|
|
//! Timestamp formatting.
|
|
|
|
|
|
2020-05-18 19:52:59 +00:00
|
|
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
2018-12-17 01:51:55 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
use datetime::{LocalDateTime, TimeZone, DatePiece, TimePiece, Month};
|
2017-07-03 07:45:14 +00:00
|
|
|
|
use datetime::fmt::DateFormat;
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
|
|
|
|
|
use lazy_static::lazy_static;
|
|
|
|
|
use unicode_width::UnicodeWidthStr;
|
2017-07-03 07:45:14 +00:00
|
|
|
|
|
|
|
|
|
|
2017-08-09 16:14:16 +00:00
|
|
|
|
/// Every timestamp in exa needs to be rendered by a **time format**.
|
|
|
|
|
/// Formatting times is tricky, because how a timestamp is rendered can
|
|
|
|
|
/// depend on one or more of the following:
|
|
|
|
|
///
|
|
|
|
|
/// - The user’s locale, for printing the month name as “Feb”, or as “fév”,
|
|
|
|
|
/// or as “2月”;
|
|
|
|
|
/// - The current year, because certain formats will be less precise when
|
|
|
|
|
/// dealing with dates far in the past;
|
|
|
|
|
/// - The formatting style that the user asked for on the command-line.
|
|
|
|
|
///
|
|
|
|
|
/// Because not all formatting styles need the same data, they all have their
|
|
|
|
|
/// own enum variants. It’s not worth looking the locale up if the formatter
|
|
|
|
|
/// prints month names as numbers.
|
|
|
|
|
///
|
|
|
|
|
/// Currently exa does not support *custom* styles, where the user enters a
|
|
|
|
|
/// format string in an environment variable or something. Just these four.
|
2020-10-13 00:36:41 +00:00
|
|
|
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
2017-07-05 22:27:48 +00:00
|
|
|
|
pub enum TimeFormat {
|
2017-08-09 16:14:16 +00:00
|
|
|
|
|
|
|
|
|
/// The **default format** uses the user’s locale to print month names,
|
|
|
|
|
/// and specifies the timestamp down to the minute for recent times, and
|
|
|
|
|
/// day for older times.
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
DefaultFormat,
|
2017-08-09 16:14:16 +00:00
|
|
|
|
|
|
|
|
|
/// Use the **ISO format**, which specifies the timestamp down to the
|
|
|
|
|
/// minute for recent times, and day for older times. It uses a number
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
/// for the month so it doesn’t use the locale.
|
|
|
|
|
ISOFormat,
|
2017-08-09 16:14:16 +00:00
|
|
|
|
|
|
|
|
|
/// Use the **long ISO format**, which specifies the timestamp down to the
|
|
|
|
|
/// minute using only numbers, without needing the locale or year.
|
2017-07-05 23:21:38 +00:00
|
|
|
|
LongISO,
|
2017-08-09 16:14:16 +00:00
|
|
|
|
|
|
|
|
|
/// Use the **full ISO format**, which specifies the timestamp down to the
|
|
|
|
|
/// millisecond and includes its offset down to the minute. This too uses
|
|
|
|
|
/// only numbers so doesn’t require any special consideration.
|
2017-07-05 23:21:38 +00:00
|
|
|
|
FullISO,
|
2017-07-05 22:27:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-09 16:14:16 +00:00
|
|
|
|
// There are two different formatting functions because local and zoned
|
|
|
|
|
// timestamps are separate types.
|
|
|
|
|
|
2017-07-05 22:27:48 +00:00
|
|
|
|
impl TimeFormat {
|
2020-10-13 00:46:17 +00:00
|
|
|
|
pub fn format_local(self, time: SystemTime) -> String {
|
2020-10-10 14:30:19 +00:00
|
|
|
|
match self {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
Self::DefaultFormat => default_local(time),
|
|
|
|
|
Self::ISOFormat => iso_local(time),
|
|
|
|
|
Self::LongISO => long_local(time),
|
|
|
|
|
Self::FullISO => full_local(time),
|
2017-07-05 22:27:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-13 00:46:17 +00:00
|
|
|
|
pub fn format_zoned(self, time: SystemTime, zone: &TimeZone) -> String {
|
2020-10-10 14:30:19 +00:00
|
|
|
|
match self {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
Self::DefaultFormat => default_zoned(time, zone),
|
|
|
|
|
Self::ISOFormat => iso_zoned(time, zone),
|
|
|
|
|
Self::LongISO => long_zoned(time, zone),
|
|
|
|
|
Self::FullISO => full_zoned(time, zone),
|
2017-07-05 22:27:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
|
|
|
|
fn default_local(time: SystemTime) -> String {
|
|
|
|
|
let date = LocalDateTime::at(systemtime_epoch(time));
|
2019-06-11 00:34:21 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
if date.year() == *CURRENT_YEAR {
|
|
|
|
|
format!("{:2} {} {:02}:{:02}",
|
|
|
|
|
date.day(), month_to_abbrev(date.month()),
|
|
|
|
|
date.hour(), date.minute())
|
2017-07-03 07:45:14 +00:00
|
|
|
|
}
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
else {
|
|
|
|
|
let date_format = match *MAXIMUM_MONTH_WIDTH {
|
|
|
|
|
4 => &*FOUR_WIDE_DATE_TIME,
|
|
|
|
|
5 => &*FIVE_WIDE_DATE_TIME,
|
|
|
|
|
_ => &*OTHER_WIDE_DATE_TIME,
|
|
|
|
|
};
|
2017-07-03 07:45:14 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
date_format.format(&date, &*LOCALE)
|
2019-06-11 00:34:21 +00:00
|
|
|
|
}
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
}
|
2019-06-11 00:34:21 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
|
|
|
|
fn default_zoned(time: SystemTime, zone: &TimeZone) -> String {
|
|
|
|
|
let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time)));
|
2017-07-03 07:45:14 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
if date.year() == *CURRENT_YEAR {
|
|
|
|
|
format!("{:2} {} {:02}:{:02}",
|
|
|
|
|
date.day(), month_to_abbrev(date.month()),
|
|
|
|
|
date.hour(), date.minute())
|
2017-07-03 07:45:14 +00:00
|
|
|
|
}
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
else {
|
|
|
|
|
let date_format = match *MAXIMUM_MONTH_WIDTH {
|
|
|
|
|
4 => &*FOUR_WIDE_DATE_YEAR,
|
|
|
|
|
5 => &*FIVE_WIDE_DATE_YEAR,
|
|
|
|
|
_ => &*OTHER_WIDE_DATE_YEAR,
|
|
|
|
|
};
|
2017-07-03 07:45:14 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
date_format.format(&date, &*LOCALE)
|
2017-07-03 07:45:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-07-05 23:01:45 +00:00
|
|
|
|
|
2017-07-05 23:21:38 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
2020-05-18 19:52:59 +00:00
|
|
|
|
fn long_local(time: SystemTime) -> String {
|
|
|
|
|
let date = LocalDateTime::at(systemtime_epoch(time));
|
2017-07-05 23:21:38 +00:00
|
|
|
|
format!("{:04}-{:02}-{:02} {:02}:{:02}",
|
|
|
|
|
date.year(), date.month() as usize, date.day(),
|
|
|
|
|
date.hour(), date.minute())
|
|
|
|
|
}
|
2017-07-05 23:01:45 +00:00
|
|
|
|
|
2017-07-05 23:21:38 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
2020-05-18 19:52:59 +00:00
|
|
|
|
fn long_zoned(time: SystemTime, zone: &TimeZone) -> String {
|
|
|
|
|
let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time)));
|
2017-07-05 23:21:38 +00:00
|
|
|
|
format!("{:04}-{:02}-{:02} {:02}:{:02}",
|
|
|
|
|
date.year(), date.month() as usize, date.day(),
|
|
|
|
|
date.hour(), date.minute())
|
|
|
|
|
}
|
2017-07-05 23:01:45 +00:00
|
|
|
|
|
2017-07-05 23:21:38 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
2020-05-18 19:52:59 +00:00
|
|
|
|
fn full_local(time: SystemTime) -> String {
|
|
|
|
|
let date = LocalDateTime::at(systemtime_epoch(time));
|
2017-07-05 23:21:38 +00:00
|
|
|
|
format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:09}",
|
|
|
|
|
date.year(), date.month() as usize, date.day(),
|
2020-05-18 19:52:59 +00:00
|
|
|
|
date.hour(), date.minute(), date.second(), systemtime_nanos(time))
|
2017-07-05 23:21:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(trivial_numeric_casts)]
|
2020-05-18 19:52:59 +00:00
|
|
|
|
fn full_zoned(time: SystemTime, zone: &TimeZone) -> String {
|
2017-07-05 23:21:38 +00:00
|
|
|
|
use datetime::Offset;
|
|
|
|
|
|
2020-05-18 19:52:59 +00:00
|
|
|
|
let local = LocalDateTime::at(systemtime_epoch(time));
|
2017-07-05 23:21:38 +00:00
|
|
|
|
let date = zone.to_zoned(local);
|
|
|
|
|
let offset = Offset::of_seconds(zone.offset(local) as i32).expect("Offset out of range");
|
|
|
|
|
format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:09} {:+03}{:02}",
|
|
|
|
|
date.year(), date.month() as usize, date.day(),
|
2020-05-18 19:52:59 +00:00
|
|
|
|
date.hour(), date.minute(), date.second(), systemtime_nanos(time),
|
2017-07-05 23:21:38 +00:00
|
|
|
|
offset.hours(), offset.minutes().abs())
|
2017-07-05 23:01:45 +00:00
|
|
|
|
}
|
2017-07-05 23:39:54 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
|
|
|
|
fn iso_local(time: SystemTime) -> String {
|
|
|
|
|
let date = LocalDateTime::at(systemtime_epoch(time));
|
2017-07-05 23:39:54 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
if is_recent(date) {
|
|
|
|
|
format!("{:02}-{:02} {:02}:{:02}",
|
|
|
|
|
date.month() as usize, date.day(),
|
|
|
|
|
date.hour(), date.minute())
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
format!("{:04}-{:02}-{:02}",
|
|
|
|
|
date.year(), date.month() as usize, date.day())
|
|
|
|
|
}
|
2017-07-05 23:39:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
#[allow(trivial_numeric_casts)]
|
|
|
|
|
fn iso_zoned(time: SystemTime, zone: &TimeZone) -> String {
|
|
|
|
|
let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time)));
|
|
|
|
|
|
|
|
|
|
if is_recent(date) {
|
|
|
|
|
format!("{:02}-{:02} {:02}:{:02}",
|
|
|
|
|
date.month() as usize, date.day(),
|
|
|
|
|
date.hour(), date.minute())
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
format!("{:04}-{:02}-{:02}",
|
|
|
|
|
date.year(), date.month() as usize, date.day())
|
2017-07-05 23:39:54 +00:00
|
|
|
|
}
|
2018-06-19 12:58:03 +00:00
|
|
|
|
}
|
2017-07-05 23:39:54 +00:00
|
|
|
|
|
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
fn systemtime_epoch(time: SystemTime) -> i64 {
|
|
|
|
|
time.duration_since(UNIX_EPOCH)
|
|
|
|
|
.map(|t| t.as_secs() as i64)
|
|
|
|
|
.unwrap_or_else(|e| {
|
|
|
|
|
let diff = e.duration();
|
|
|
|
|
let mut secs = diff.as_secs();
|
|
|
|
|
if diff.subsec_nanos() > 0 {
|
|
|
|
|
secs += 1;
|
|
|
|
|
}
|
|
|
|
|
-(secs as i64)
|
|
|
|
|
})
|
|
|
|
|
}
|
2017-07-05 23:39:54 +00:00
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
fn systemtime_nanos(time: SystemTime) -> u32 {
|
|
|
|
|
time.duration_since(UNIX_EPOCH)
|
|
|
|
|
.map(|t| t.subsec_nanos())
|
|
|
|
|
.unwrap_or_else(|e| {
|
|
|
|
|
let nanos = e.duration().subsec_nanos();
|
|
|
|
|
if nanos > 0 {
|
|
|
|
|
1_000_000_000 - nanos
|
|
|
|
|
} else {
|
|
|
|
|
nanos
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_recent(date: LocalDateTime) -> bool {
|
|
|
|
|
date.year() == *CURRENT_YEAR
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn month_to_abbrev(month: Month) -> &'static str {
|
|
|
|
|
match month {
|
|
|
|
|
Month::January => "Jan",
|
|
|
|
|
Month::February => "Feb",
|
|
|
|
|
Month::March => "Mar",
|
|
|
|
|
Month::April => "Apr",
|
|
|
|
|
Month::May => "May",
|
|
|
|
|
Month::June => "Jun",
|
|
|
|
|
Month::July => "Jul",
|
|
|
|
|
Month::August => "Aug",
|
|
|
|
|
Month::September => "Sep",
|
|
|
|
|
Month::October => "Oct",
|
|
|
|
|
Month::November => "Nov",
|
|
|
|
|
Month::December => "Dec",
|
2017-07-05 23:39:54 +00:00
|
|
|
|
}
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
}
|
2017-07-05 23:39:54 +00:00
|
|
|
|
|
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
lazy_static! {
|
|
|
|
|
|
|
|
|
|
static ref CURRENT_YEAR: i64 = LocalDateTime::now().year();
|
|
|
|
|
|
|
|
|
|
static ref LOCALE: locale::Time = {
|
|
|
|
|
locale::Time::load_user_locale()
|
|
|
|
|
.unwrap_or_else(|_| locale::Time::english())
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static ref MAXIMUM_MONTH_WIDTH: usize = {
|
|
|
|
|
// Some locales use a three-character wide month name (Jan to Dec);
|
|
|
|
|
// others vary between three to four (1月 to 12月, juil.). We check each month width
|
|
|
|
|
// to detect the longest and set the output format accordingly.
|
|
|
|
|
let mut maximum_month_width = 0;
|
|
|
|
|
for i in 0..11 {
|
|
|
|
|
let current_month_width = UnicodeWidthStr::width(&*LOCALE.short_month_name(i));
|
|
|
|
|
maximum_month_width = std::cmp::max(maximum_month_width, current_month_width);
|
2017-08-06 10:36:00 +00:00
|
|
|
|
}
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 22:47:36 +00:00
|
|
|
|
maximum_month_width
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static ref FOUR_WIDE_DATE_TIME: DateFormat<'static> = DateFormat::parse(
|
|
|
|
|
"{2>:D} {4<:M} {2>:h}:{02>:m}"
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
|
static ref FIVE_WIDE_DATE_TIME: DateFormat<'static> = DateFormat::parse(
|
|
|
|
|
"{2>:D} {5<:M} {2>:h}:{02>:m}"
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
|
static ref OTHER_WIDE_DATE_TIME: DateFormat<'static> = DateFormat::parse(
|
|
|
|
|
"{2>:D} {:M} {2>:h}:{02>:m}"
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
|
static ref FOUR_WIDE_DATE_YEAR: DateFormat<'static> = DateFormat::parse(
|
|
|
|
|
"{2>:D} {4<:M} {5>:Y}"
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
|
static ref FIVE_WIDE_DATE_YEAR: DateFormat<'static> = DateFormat::parse(
|
|
|
|
|
"{2>:D} {5<:M} {5>:Y}"
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
|
static ref OTHER_WIDE_DATE_YEAR: DateFormat<'static> = DateFormat::parse(
|
|
|
|
|
"{2>:D} {:M} {5>:Y}"
|
|
|
|
|
).unwrap();
|
2017-07-05 23:39:54 +00:00
|
|
|
|
}
|