pub struct DateTimePrinter { /* private fields */ }
Expand description
A printer for Temporal datetimes.
This printer converts an in memory representation of a datetime related
type to a machine (but also human) readable format. Using this printer, one
can convert Zoned
, Timestamp
, civil::DateTime
, civil::Date
or civil::Time
values to a string. Note that all of those types provide
Diplay
implementations that utilize the default
configuration of this printer. However, this printer can be configured to
behave differently and can also print directly to anything that implements
the fmt::Write
trait.
See the fmt::temporal
module documentation for
more information on the specific format used. Note that the Temporal
datetime parser is strictly more flexible than what is supported by this
printer. For example, parsing 2024-06-15T07:00-04[America/New_York]
will
work just fine, even though the seconds are omitted. However, this printer
provides no way to write a datetime without the second component.
§Example
This example shows how to print a Zoned
value with a space separating
the date and time instead of the more standard T
separator.
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
// A printer can be created in a const context.
const PRINTER: DateTimePrinter = DateTimePrinter::new().separator(b' ');
let zdt = date(2024, 6, 15).at(7, 0, 0, 123456789).in_tz("America/New_York")?;
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_zoned(&zdt, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15 07:00:00.123456789-04:00[America/New_York]");
§Example: using adapters with std::io::Write
and std::fmt::Write
By using the StdIoWrite
and
StdFmtWrite
adapters, one can print datetimes
directly to implementations of std::io::Write
and std::fmt::Write
,
respectively. The example below demonstrates writing to anything
that implements std::io::Write
. Similar code can be written for
std::fmt::Write
.
use std::{fs::File, io::{BufWriter, Write}, path::Path};
use jiff::{civil::date, fmt::{StdIoWrite, temporal::DateTimePrinter}};
let zdt = date(2024, 6, 15).at(7, 0, 0, 0).in_tz("America/New_York")?;
let path = Path::new("/tmp/output");
let mut file = BufWriter::new(File::create(path)?);
DateTimePrinter::new().print_zoned(&zdt, StdIoWrite(&mut file)).unwrap();
file.flush()?;
assert_eq!(
std::fs::read_to_string(path)?,
"2024-06-15T07:00:00-04:00[America/New_York]",
);
Implementations§
Source§impl DateTimePrinter
impl DateTimePrinter
Sourcepub const fn new() -> DateTimePrinter
pub const fn new() -> DateTimePrinter
Create a new Temporal datetime printer with the default configuration.
Sourcepub const fn lowercase(self, yes: bool) -> DateTimePrinter
pub const fn lowercase(self, yes: bool) -> DateTimePrinter
Use lowercase for the datetime separator and the Z
(Zulu) UTC offset.
This is disabled by default.
§Example
This example shows how to print a Zoned
value with a lowercase
datetime separator.
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new().lowercase(true);
let zdt = date(2024, 6, 15).at(7, 0, 0, 0).in_tz("America/New_York")?;
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_zoned(&zdt, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15t07:00:00-04:00[America/New_York]");
Sourcepub const fn separator(self, ascii_char: u8) -> DateTimePrinter
pub const fn separator(self, ascii_char: u8) -> DateTimePrinter
Use the given ASCII character to separate the date and time when
printing Zoned
, Timestamp
or civil::DateTime
values.
This is set to T
by default.
§Example
This example shows how to print a Zoned
value with a different
datetime separator.
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
// We use a weird non-standard character here, but typically one would
// use this method with an ASCII space.
const PRINTER: DateTimePrinter = DateTimePrinter::new().separator(b'~');
let zdt = date(2024, 6, 15).at(7, 0, 0, 0).in_tz("America/New_York")?;
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_zoned(&zdt, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15~07:00:00-04:00[America/New_York]");
Sourcepub const fn precision(self, precision: Option<u8>) -> DateTimePrinter
pub const fn precision(self, precision: Option<u8>) -> DateTimePrinter
Set the precision to use for formatting the fractional second component of a time.
The default is None
, which will automatically set the precision based
on the value.
When the precision is set to N
, you’ll always get precisely N
digits after a decimal point (unless N==0
, then no fractional
component is printed), even if they are 0
.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter =
DateTimePrinter::new().precision(Some(3));
let zdt = date(2024, 6, 15).at(7, 0, 0, 123_456_789).in_tz("US/Eastern")?;
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_zoned(&zdt, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15T07:00:00.123-04:00[US/Eastern]");
§Example: available via formatting machinery
When formatting datetime types that may contain a fractional second
component, this can be set via Rust’s formatting DSL. Specifically,
it corresponds to the std::fmt::Formatter::precision
setting.
use jiff::civil::date;
let zdt = date(2024, 6, 15).at(7, 0, 0, 123_000_000).in_tz("US/Eastern")?;
assert_eq!(
format!("{zdt:.6}"),
"2024-06-15T07:00:00.123000-04:00[US/Eastern]",
);
// Precision values greater than 9 are clamped to 9.
assert_eq!(
format!("{zdt:.300}"),
"2024-06-15T07:00:00.123000000-04:00[US/Eastern]",
);
// A precision of 0 implies the entire fractional
// component is always truncated.
assert_eq!(
format!("{zdt:.0}"),
"2024-06-15T07:00:00-04:00[US/Eastern]",
);
Sourcepub fn zoned_to_string(&self, zdt: &Zoned) -> String
pub fn zoned_to_string(&self, zdt: &Zoned) -> String
Format a Zoned
datetime into a string.
This is a convenience routine for DateTimePrinter::print_zoned
with
a String
.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let zdt = date(2024, 6, 15).at(7, 0, 0, 0).in_tz("America/New_York")?;
assert_eq!(
PRINTER.zoned_to_string(&zdt),
"2024-06-15T07:00:00-04:00[America/New_York]",
);
Sourcepub fn timestamp_to_string(&self, timestamp: &Timestamp) -> String
pub fn timestamp_to_string(&self, timestamp: &Timestamp) -> String
Format a Timestamp
datetime into a string.
This will always return an RFC 3339 compatible string with a Z
or
Zulu offset. Zulu is chosen in accordance with RFC 9557’s update to
RFC 3339 that establishes the -00:00
offset as equivalent to Zulu:
If the time in UTC is known, but the offset to local time is unknown, this can be represented with an offset of “Z”. (The original version of this specification provided -00:00 for this purpose, which is not allowed by ISO8601:2000 and therefore is less interoperable; Section 3.3 of RFC5322 describes a related convention for email, which does not have this problem). This differs semantically from an offset of +00:00, which implies that UTC is the preferred reference point for the specified time.
In other words, both Zulu time and -00:00
mean “the time in UTC is
known, but the offset to local time is unknown.”
If you need to format an RFC 3339 timestamp with a specific offset,
use DateTimePrinter::timestamp_with_offset_to_string
.
This is a convenience routine for DateTimePrinter::print_timestamp
with a String
.
§Example
use jiff::{fmt::temporal::DateTimePrinter, Timestamp};
let timestamp = Timestamp::new(0, 1)
.expect("one nanosecond after Unix epoch is always valid");
assert_eq!(
DateTimePrinter::new().timestamp_to_string(×tamp),
"1970-01-01T00:00:00.000000001Z",
);
Sourcepub fn timestamp_with_offset_to_string(
&self,
timestamp: &Timestamp,
offset: Offset,
) -> String
pub fn timestamp_with_offset_to_string( &self, timestamp: &Timestamp, offset: Offset, ) -> String
Format a Timestamp
datetime into a string with the given offset.
This will always return an RFC 3339 compatible string with an offset.
This will never use either Z
(for Zulu time) or -00:00
as an
offset. This is because Zulu time (and -00:00
) mean “the time in UTC
is known, but the offset to local time is unknown.” Since this routine
accepts an explicit offset, the offset is known. For example,
Offset::UTC
will be formatted as +00:00
.
To format an RFC 3339 string in Zulu time, use
DateTimePrinter::timestamp_to_string
.
This is a convenience routine for
DateTimePrinter::print_timestamp_with_offset
with a String
.
§Example
use jiff::{fmt::temporal::DateTimePrinter, tz, Timestamp};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let timestamp = Timestamp::new(0, 1)
.expect("one nanosecond after Unix epoch is always valid");
assert_eq!(
PRINTER.timestamp_with_offset_to_string(×tamp, tz::offset(-5)),
"1969-12-31T19:00:00.000000001-05:00",
);
§Example: Offset::UTC
formats as +00:00
use jiff::{fmt::temporal::DateTimePrinter, tz::Offset, Timestamp};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let timestamp = Timestamp::new(0, 1)
.expect("one nanosecond after Unix epoch is always valid");
assert_eq!(
PRINTER.timestamp_with_offset_to_string(×tamp, Offset::UTC),
"1970-01-01T00:00:00.000000001+00:00",
);
Sourcepub fn datetime_to_string(&self, dt: &DateTime) -> String
pub fn datetime_to_string(&self, dt: &DateTime) -> String
Format a civil::DateTime
into a string.
This is a convenience routine for DateTimePrinter::print_datetime
with a String
.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let dt = date(2024, 6, 15).at(7, 0, 0, 0);
assert_eq!(PRINTER.datetime_to_string(&dt), "2024-06-15T07:00:00");
Sourcepub fn date_to_string(&self, date: &Date) -> String
pub fn date_to_string(&self, date: &Date) -> String
Format a civil::Date
into a string.
This is a convenience routine for DateTimePrinter::print_date
with a String
.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let d = date(2024, 6, 15);
assert_eq!(PRINTER.date_to_string(&d), "2024-06-15");
Sourcepub fn time_to_string(&self, time: &Time) -> String
pub fn time_to_string(&self, time: &Time) -> String
Format a civil::Time
into a string.
This is a convenience routine for DateTimePrinter::print_time
with a String
.
§Example
use jiff::{civil::time, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let t = time(7, 0, 0, 0);
assert_eq!(PRINTER.time_to_string(&t), "07:00:00");
Sourcepub fn time_zone_to_string(&self, tz: &TimeZone) -> Result<String, Error>
pub fn time_zone_to_string(&self, tz: &TimeZone) -> Result<String, Error>
Format a TimeZone
into a string.
This is a convenience routine for DateTimePrinter::print_time_zone
.
§Errors
In some rare cases, serialization may fail when there is no succinct
representation of a time zone. One specific case in which this
occurs is when TimeZone
is a user’s system time zone derived from
/etc/localtime
, but where an IANA time zone identifier could not
be found. This can occur, for example, when /etc/localtime
is not
symlinked to an entry in /usr/share/zoneinfo
.
§Example
use jiff::{fmt::temporal::DateTimePrinter, tz::{self, TimeZone}};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
// IANA time zone
let tz = TimeZone::get("US/Eastern")?;
assert_eq!(PRINTER.time_zone_to_string(&tz)?, "US/Eastern");
Sourcepub fn pieces_to_string(&self, pieces: &Pieces<'_>) -> String
pub fn pieces_to_string(&self, pieces: &Pieces<'_>) -> String
Format Pieces
of a Temporal datetime.
This is a convenience routine for DateTimePrinter::print_pieces
with a String
.
§Example
use jiff::{
fmt::temporal::{DateTimePrinter, Pieces},
tz::offset,
Timestamp,
};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let pieces = Pieces::from(Timestamp::UNIX_EPOCH);
assert_eq!(
PRINTER.pieces_to_string(&pieces),
"1970-01-01T00:00:00Z",
);
let pieces = Pieces::from((Timestamp::UNIX_EPOCH, offset(0)));
assert_eq!(
PRINTER.pieces_to_string(&pieces),
"1970-01-01T00:00:00+00:00",
);
let pieces = Pieces::from((Timestamp::UNIX_EPOCH, offset(-5)));
assert_eq!(
PRINTER.pieces_to_string(&pieces),
"1969-12-31T19:00:00-05:00",
);
Sourcepub fn print_zoned<W: Write>(&self, zdt: &Zoned, wtr: W) -> Result<(), Error>
pub fn print_zoned<W: Write>(&self, zdt: &Zoned, wtr: W) -> Result<(), Error>
Print a Zoned
datetime to the given writer.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let zdt = date(2024, 6, 15).at(7, 0, 0, 0).in_tz("America/New_York")?;
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_zoned(&zdt, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15T07:00:00-04:00[America/New_York]");
Sourcepub fn print_timestamp<W: Write>(
&self,
timestamp: &Timestamp,
wtr: W,
) -> Result<(), Error>
pub fn print_timestamp<W: Write>( &self, timestamp: &Timestamp, wtr: W, ) -> Result<(), Error>
Print a Timestamp
datetime to the given writer.
This will always write an RFC 3339 compatible string with a Z
or
Zulu offset. Zulu is chosen in accordance with RFC 9557’s update to
RFC 3339 that establishes the -00:00
offset as equivalent to Zulu:
If the time in UTC is known, but the offset to local time is unknown, this can be represented with an offset of “Z”. (The original version of this specification provided -00:00 for this purpose, which is not allowed by ISO8601:2000 and therefore is less interoperable; Section 3.3 of RFC5322 describes a related convention for email, which does not have this problem). This differs semantically from an offset of +00:00, which implies that UTC is the preferred reference point for the specified time.
In other words, both Zulu time and -00:00
mean “the time in UTC is
known, but the offset to local time is unknown.”
If you need to write an RFC 3339 timestamp with a specific offset,
use DateTimePrinter::print_timestamp_with_offset
.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{fmt::temporal::DateTimePrinter, Timestamp};
let timestamp = Timestamp::new(0, 1)
.expect("one nanosecond after Unix epoch is always valid");
let mut buf = String::new();
// Printing to a `String` can never fail.
DateTimePrinter::new().print_timestamp(×tamp, &mut buf).unwrap();
assert_eq!(buf, "1970-01-01T00:00:00.000000001Z");
Sourcepub fn print_timestamp_with_offset<W: Write>(
&self,
timestamp: &Timestamp,
offset: Offset,
wtr: W,
) -> Result<(), Error>
pub fn print_timestamp_with_offset<W: Write>( &self, timestamp: &Timestamp, offset: Offset, wtr: W, ) -> Result<(), Error>
Print a Timestamp
datetime to the given writer with the given offset.
This will always write an RFC 3339 compatible string with an offset.
This will never write either Z
(for Zulu time) or -00:00
as an
offset. This is because Zulu time (and -00:00
) mean “the time in UTC
is known, but the offset to local time is unknown.” Since this routine
accepts an explicit offset, the offset is known. For example,
Offset::UTC
will be formatted as +00:00
.
To write an RFC 3339 string in Zulu time, use
DateTimePrinter::print_timestamp
.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{fmt::temporal::DateTimePrinter, tz, Timestamp};
let timestamp = Timestamp::new(0, 1)
.expect("one nanosecond after Unix epoch is always valid");
let mut buf = String::new();
// Printing to a `String` can never fail.
DateTimePrinter::new().print_timestamp_with_offset(
×tamp,
tz::offset(-5),
&mut buf,
).unwrap();
assert_eq!(buf, "1969-12-31T19:00:00.000000001-05:00");
§Example: Offset::UTC
formats as +00:00
use jiff::{fmt::temporal::DateTimePrinter, tz::Offset, Timestamp};
let timestamp = Timestamp::new(0, 1)
.expect("one nanosecond after Unix epoch is always valid");
let mut buf = String::new();
// Printing to a `String` can never fail.
DateTimePrinter::new().print_timestamp_with_offset(
×tamp,
Offset::UTC, // equivalent to `Offset::from_hours(0)`
&mut buf,
).unwrap();
assert_eq!(buf, "1970-01-01T00:00:00.000000001+00:00");
Sourcepub fn print_datetime<W: Write>(
&self,
dt: &DateTime,
wtr: W,
) -> Result<(), Error>
pub fn print_datetime<W: Write>( &self, dt: &DateTime, wtr: W, ) -> Result<(), Error>
Print a civil::DateTime
to the given writer.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let d = date(2024, 6, 15).at(7, 0, 0, 0);
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_datetime(&d, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15T07:00:00");
Sourcepub fn print_date<W: Write>(&self, date: &Date, wtr: W) -> Result<(), Error>
pub fn print_date<W: Write>(&self, date: &Date, wtr: W) -> Result<(), Error>
Print a civil::Date
to the given writer.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{civil::date, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let d = date(2024, 6, 15);
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_date(&d, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15");
Sourcepub fn print_time<W: Write>(&self, time: &Time, wtr: W) -> Result<(), Error>
pub fn print_time<W: Write>(&self, time: &Time, wtr: W) -> Result<(), Error>
Print a civil::Time
to the given writer.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{civil::time, fmt::temporal::DateTimePrinter};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let t = time(7, 0, 0, 0);
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_time(&t, &mut buf).unwrap();
assert_eq!(buf, "07:00:00");
Sourcepub fn print_time_zone<W: Write>(
&self,
tz: &TimeZone,
wtr: W,
) -> Result<(), Error>
pub fn print_time_zone<W: Write>( &self, tz: &TimeZone, wtr: W, ) -> Result<(), Error>
Print a TimeZone
.
This will emit one of three different categories of strings:
- An IANA Time Zone Database identifier. For example,
America/New_York
orUTC
. - A fixed offset. For example,
-05:00
or-00:44:30
. - A POSIX time zone string. For example,
EST5EDT,M3.2.0,M11.1.0
.
§Differences with RFC 9557 annotations
Jiff’s Offset
has second precision. If a TimeZone
is a fixed
offset and has fractional minutes, then they will be expressed in the
[+-]HH:MM:SS
format. Otherwise, the :SS
will be omitted.
This differs from RFC 3339 and RFC 9557 because neither support
sub-minute resolution in UTC offsets. Indeed, if one were to format
a Zoned
with an offset that contains fractional minutes, the offset
would be rounded to the nearest minute to preserve compatibility with
RFC 3339 and RFC 9557. However, this routine does no such rounding.
This is because there is no RFC standardizing the serialization of
a lone time zone, and there is otherwise no need to reduce an offset’s
precision.
§Errors
In some rare cases, serialization may fail when there is no succinct
representation of a time zone. One specific case in which this
occurs is when TimeZone
is a user’s system time zone derived from
/etc/localtime
, but where an IANA time zone identifier could not
be found. This can occur, for example, when /etc/localtime
is not
symlinked to an entry in /usr/share/zoneinfo
.
An error can also occur when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails).
§Example
use jiff::{fmt::temporal::DateTimePrinter, tz::{self, TimeZone}};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
// IANA time zone
let tz = TimeZone::get("US/Eastern")?;
let mut buf = String::new();
PRINTER.print_time_zone(&tz, &mut buf)?;
assert_eq!(buf, "US/Eastern");
// Fixed offset
let tz = TimeZone::fixed(tz::offset(-5));
let mut buf = String::new();
PRINTER.print_time_zone(&tz, &mut buf)?;
assert_eq!(buf, "-05:00");
// POSIX time zone
let tz = TimeZone::posix("EST5EDT,M3.2.0,M11.1.0")?;
let mut buf = String::new();
PRINTER.print_time_zone(&tz, &mut buf)?;
assert_eq!(buf, "EST5EDT,M3.2.0,M11.1.0");
// The error case for a time zone that doesn't fall
// into one of the three categories about is not easy
// to create artificially. The only way, at time of
// writing, to produce it is via `TimeZone::system()`
// with a non-symlinked `/etc/timezone`. (Or `TZ` set
// to the path of a similar file.)
Sourcepub fn print_pieces<W: Write>(
&self,
pieces: &Pieces<'_>,
wtr: W,
) -> Result<(), Error>
pub fn print_pieces<W: Write>( &self, pieces: &Pieces<'_>, wtr: W, ) -> Result<(), Error>
Print the Pieces
of a Temporal datetime.
§Errors
This only returns an error when writing to the given Write
implementation would fail. Some such implementations, like for String
and Vec<u8>
, never fail (unless memory allocation fails). In such
cases, it would be appropriate to call unwrap()
on the result.
§Example
use jiff::{civil::date, fmt::temporal::{DateTimePrinter, Pieces}};
const PRINTER: DateTimePrinter = DateTimePrinter::new();
let pieces = Pieces::from(date(2024, 6, 15))
.with_time_zone_name("US/Eastern");
let mut buf = String::new();
// Printing to a `String` can never fail.
PRINTER.print_pieces(&pieces, &mut buf).unwrap();
assert_eq!(buf, "2024-06-15[US/Eastern]");