Skip to content

Commit 44a294f

Browse files
authored
Merge pull request #95 from Drakulix/fix/chrono_dep
Replace chrono with time
2 parents 81c6293 + cf8fc32 commit 44a294f

File tree

7 files changed

+115
-40
lines changed

7 files changed

+115
-40
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
## v0.12.0
2+
- Replaces the semingly unmainted chrono library with the time crate.
3+
- Addresses through this update
4+
- RUSTSEC-2020-0159 (chrono)
5+
- RUSTSEC-2020-0071 (time)
6+
- `ConfigBuilder::set_time_to_local` is replaced by `ConfigBuilder::set_time_offset_to_local`.
7+
- This function requires the new (and by default activated) `local-offset` feature.
8+
- This function may fail, for more information read the docs.
9+
- simplelog will not determine the local offset dynamically anymore, but only once, when this config option is set.
10+
- Due to safety reasons there is no way to provide this property currently.
11+
- `ConfigBuilder::set_time_offset` now takes a `time::UtcOffset` instead of a `chrono::FixedOffset`.
12+
- `ConfigBuilder::set_time_format` has been replaced by three new variants
13+
- `ConfigBuilder::set_time_format_rfc2822` sets the time format to use the format described by rfc2822.
14+
- `ConfigBuilder::set_time_format_rfc3339` sets the time format to use the format described by rfc3339.
15+
- `ConfigBuilder::set_time_format_custom` sets the time format to a custom time format best created using `time::macros::format_description`.
16+
- Runtime provided time format configuration is possible, but difficult due to lifetime constraints.
17+
- Fixing this will require a solution to https://github.com/time-rs/time/issues/429
18+
- *Note*: The default format is unchanged "[hour]:[minute]:[second]"
19+
120
## v0.11.0
221
- Add colored log levels using `ansi_term` (PR #88, credits to @manio)
322
- Add target padding (PR #85, credits to @bytebeamio)

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "simplelog"
3-
version = "0.11.2"
3+
version = "0.12.0-alpha1"
44
edition = "2018"
55
authors = ["Drakulix <github@drakulix.de>"]
66
description = "A simple and easy-to-use logging facility for Rust's log crate"
@@ -20,11 +20,12 @@ include = [
2020

2121
[features]
2222
test = []
23-
default = ["termcolor"]
23+
default = ["termcolor", "local-offset"]
24+
local-offset = ["time/local-offset"]
2425

2526
[dependencies]
2627
log = { version = "0.4.*", features = ["std"] }
2728
termcolor = { version = "1.1.*", optional = true }
2829
paris = { version = "~1.5", optional = true }
2930
ansi_term = { version = "0.12", optional = true }
30-
chrono = "0.4.1"
31+
time = { version = "0.3.7", features = ["formatting", "macros"] }

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn main() {
4242
### Results in
4343
```
4444
$ cargo run --example usage
45-
Compiling simplelog v0.10.0 (file:///home/drakulix/Projects/simplelog)
45+
Compiling simplelog v0.12.0 (file:///home/drakulix/Projects/simplelog)
4646
Running `target/debug/examples/usage`
4747
[ERROR] Bright red error
4848
```
@@ -57,7 +57,7 @@ and my_rust_binary.log
5757
Just add
5858
```
5959
[dependencies]
60-
simplelog = "^0.10.0"
60+
simplelog = "^0.12.0"
6161
```
6262
to your `Cargo.toml`
6363

src/config.rs

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
use log::Level;
33
use log::LevelFilter;
44

5-
pub use chrono::offset::{FixedOffset, Local, Offset, TimeZone, Utc};
65
use std::borrow::Cow;
76
#[cfg(feature = "termcolor")]
87
use termcolor::Color;
8+
pub use time::{format_description::FormatItem, macros::format_description, UtcOffset};
99

1010
#[derive(Debug, Clone, Copy)]
1111
/// Padding to be used for logging the level
@@ -51,6 +51,13 @@ pub enum ThreadLogMode {
5151
Both,
5252
}
5353

54+
#[derive(Debug, Clone)]
55+
pub(crate) enum TimeFormat {
56+
Rfc2822,
57+
Rfc3339,
58+
Custom(&'static [time::format_description::FormatItem<'static>]),
59+
}
60+
5461
/// Configuration for the Loggers
5562
///
5663
/// All loggers print the message in the following form:
@@ -72,9 +79,8 @@ pub struct Config {
7279
pub(crate) target: LevelFilter,
7380
pub(crate) target_padding: TargetPadding,
7481
pub(crate) location: LevelFilter,
75-
pub(crate) time_format: Cow<'static, str>,
76-
pub(crate) time_offset: FixedOffset,
77-
pub(crate) time_local: bool,
82+
pub(crate) time_format: TimeFormat,
83+
pub(crate) time_offset: UtcOffset,
7884
pub(crate) filter_allow: Cow<'static, [Cow<'static, str>]>,
7985
pub(crate) filter_ignore: Cow<'static, [Cow<'static, str>]>,
8086
#[cfg(feature = "termcolor")]
@@ -167,34 +173,68 @@ impl ConfigBuilder {
167173
self
168174
}
169175

170-
/// Set time chrono [strftime] format string.
176+
/// Sets the time format to a custom representation.
177+
///
178+
/// The easiest way to satisfy the static lifetime of the argument is to directly use the
179+
/// re-exported [`time::macros::format_description`] macro.
180+
///
181+
/// *Note*: The default time format is "[hour]:[minute]:[second]".
182+
///
183+
/// The syntax for the format_description macro can be found in the
184+
/// [`time` crate book](https://time-rs.github.io/book/api/format-description.html).
171185
///
172-
/// [strftime]: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers
173-
pub fn set_time_format_str(&mut self, time_format: &'static str) -> &mut ConfigBuilder {
174-
self.0.time_format = Cow::Borrowed(time_format);
186+
/// # Usage
187+
///
188+
/// ```
189+
/// # use simplelog::{ConfigBuilder, format_description};
190+
/// let config = ConfigBuilder::new()
191+
/// .set_time_format_custom(format_description!("[hour]:[minute]:[second].[subsecond]"))
192+
/// .build();
193+
/// ```
194+
pub fn set_time_format_custom(
195+
&mut self,
196+
time_format: &'static [FormatItem<'static>],
197+
) -> &mut ConfigBuilder {
198+
self.0.time_format = TimeFormat::Custom(time_format);
175199
self
176200
}
177201

178-
/// Set time chrono [strftime] format string.
179-
///
180-
/// [strftime]: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers
181-
pub fn set_time_format(&mut self, time_format: String) -> &mut ConfigBuilder {
182-
self.0.time_format = Cow::Owned(time_format);
202+
/// Set time format string to use rfc2822.
203+
pub fn set_time_format_rfc2822(&mut self) -> &mut ConfigBuilder {
204+
self.0.time_format = TimeFormat::Rfc2822;
183205
self
184206
}
185207

186-
/// Set offset used for logging time (default is 0)
187-
pub fn set_time_offset(&mut self, time_offset: FixedOffset) -> &mut ConfigBuilder {
188-
self.0.time_offset = time_offset;
208+
/// Set time format string to use rfc3339.
209+
pub fn set_time_format_rfc3339(&mut self) -> &mut ConfigBuilder {
210+
self.0.time_format = TimeFormat::Rfc3339;
189211
self
190212
}
191213

192-
/// set if you log in local timezone or UTC (default is UTC)
193-
pub fn set_time_to_local(&mut self, local: bool) -> &mut ConfigBuilder {
194-
self.0.time_local = local;
214+
/// Set offset used for logging time (default is UTC)
215+
pub fn set_time_offset(&mut self, offset: UtcOffset) -> &mut ConfigBuilder {
216+
self.0.time_offset = offset;
195217
self
196218
}
197219

220+
/// Sets the offset used to the current local time offset
221+
/// (overriding values previously set by [`ConfigBuilder::set_time_offset`]).
222+
///
223+
/// This function may fail if the offset cannot be determined soundly.
224+
/// This may be the case, when the program is multi-threaded by the time of calling this function.
225+
/// One can opt-out of this behavior by setting `RUSTFLAGS="--cfg unsound_local_offset"`.
226+
/// Doing so is not recommended, completely untested and may cause unexpected segfaults.
227+
#[cfg(feature = "local-offset")]
228+
pub fn set_time_offset_to_local(&mut self) -> Result<&mut ConfigBuilder, &mut ConfigBuilder> {
229+
match UtcOffset::current_local_offset() {
230+
Ok(offset) => {
231+
self.0.time_offset = offset;
232+
Ok(self)
233+
}
234+
Err(_) => Err(self),
235+
}
236+
}
237+
198238
/// set if you want to write colors in the logfile (default is Off)
199239
#[cfg(feature = "ansi_term")]
200240
pub fn set_write_log_enable_colors(&mut self, local: bool) -> &mut ConfigBuilder {
@@ -284,9 +324,8 @@ impl Default for Config {
284324
target: LevelFilter::Debug,
285325
target_padding: TargetPadding::Off,
286326
location: LevelFilter::Trace,
287-
time_format: Cow::Borrowed("%H:%M:%S"),
288-
time_offset: FixedOffset::east(0),
289-
time_local: false,
327+
time_format: TimeFormat::Custom(format_description!("[hour]:[minute]:[second]")),
328+
time_offset: UtcOffset::UTC,
290329
filter_allow: Cow::Borrowed(&[]),
291330
filter_ignore: Cow::Borrowed(&[]),
292331
write_log_enable_colors: false,

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ mod config;
2525
mod loggers;
2626

2727
pub use self::config::{
28-
Config, ConfigBuilder, LevelPadding, TargetPadding, ThreadLogMode, ThreadPadding,
28+
format_description, Config, ConfigBuilder, FormatItem, LevelPadding, TargetPadding,
29+
ThreadLogMode, ThreadPadding,
2930
};
3031
#[cfg(feature = "test")]
3132
pub use self::loggers::TestLogger;

src/loggers/logging.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::config::TargetPadding;
1+
use crate::config::{TargetPadding, TimeFormat};
22
use crate::{Config, LevelPadding, ThreadLogMode, ThreadPadding};
33
use log::{LevelFilter, Record};
44
use std::io::{Error, Write};
@@ -65,13 +65,22 @@ pub fn write_time<W>(write: &mut W, config: &Config) -> Result<(), Error>
6565
where
6666
W: Write + Sized,
6767
{
68-
let cur_time = if config.time_local {
69-
(chrono::Local::now() + config.time_offset).format(&*config.time_format)
70-
} else {
71-
(chrono::Utc::now() + config.time_offset).format(&*config.time_format)
68+
use time::error::Format;
69+
use time::format_description::well_known::*;
70+
71+
let time = time::OffsetDateTime::now_utc().to_offset(config.time_offset);
72+
let res = match config.time_format {
73+
TimeFormat::Rfc2822 => time.format_into(write, &Rfc2822),
74+
TimeFormat::Rfc3339 => time.format_into(write, &Rfc3339),
75+
TimeFormat::Custom(format) => time.format_into(write, &format),
76+
};
77+
match res {
78+
Err(Format::StdIo(err)) => return Err(err),
79+
Err(err) => panic!("Invalid time format: {}", err),
80+
_ => {}
7281
};
7382

74-
write!(write, "{} ", cur_time)?;
83+
write!(write, " ")?;
7584
Ok(())
7685
}
7786

src/loggers/testlog.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! Module providing the TestLogger Implementation
99
1010
use super::logging::should_skip;
11-
use crate::{Config, LevelPadding, SharedLogger};
11+
use crate::{config::TimeFormat, Config, LevelPadding, SharedLogger};
1212
use log::{set_boxed_logger, set_max_level, LevelFilter, Log, Metadata, Record, SetLoggerError};
1313

1414
use std::thread;
@@ -128,12 +128,18 @@ pub fn log(config: &Config, record: &Record<'_>) {
128128

129129
#[inline(always)]
130130
pub fn write_time(config: &Config) {
131-
let cur_time = if config.time_local {
132-
chrono::Local::now().naive_local() + config.time_offset
133-
} else {
134-
chrono::Utc::now().naive_utc() + config.time_offset
131+
use time::format_description::well_known::*;
132+
133+
let time = time::OffsetDateTime::now_utc().to_offset(config.time_offset);
134+
let res = match config.time_format {
135+
TimeFormat::Rfc2822 => time.format(&Rfc2822),
136+
TimeFormat::Rfc3339 => time.format(&Rfc3339),
137+
TimeFormat::Custom(format) => time.format(&format),
138+
};
139+
match res {
140+
Ok(time) => println!("{} ", time),
141+
Err(err) => panic!("Invalid time format: {}", err),
135142
};
136-
print!("{} ", cur_time.format(&*config.time_format));
137143
}
138144

139145
#[inline(always)]

0 commit comments

Comments
 (0)