use crate::{
AsciiStr, Dt, DtErr, GregorianTime, STRFTIME_SIZE, Scale, TSpan, tzdb::offset_info_at_utc,
};
impl Dt {
#[cfg(feature = "alloc")]
#[inline]
pub fn to_str(&self, fmt: &str) -> Result<alloc::string::String, DtErr> {
self.to_str_with_offset(fmt, 0)
}
#[cfg(feature = "alloc")]
#[inline]
pub fn to_str_with_offset(&self, fmt: &str, secs: i32) -> Result<alloc::string::String, DtErr> {
let mut buf = [0u8; STRFTIME_SIZE];
let n = self.to_u8_with_offset(fmt, &mut buf, secs)?;
Ok(alloc::string::String::from_utf8_lossy(&buf[0..n]).into_owned())
}
#[cfg(feature = "alloc")]
#[inline]
pub fn to_str_with_tz(&self, fmt: &str, tz_name: &str) -> Result<alloc::string::String, DtErr> {
let mut buf = [0u8; STRFTIME_SIZE];
let n = self.to_u8_with_tz(fmt, &mut buf, tz_name)?;
Ok(alloc::string::String::from_utf8_lossy(&buf[0..n]).into_owned())
}
pub fn to_str_bin(&self, fmt: &str) -> Result<AsciiStr<STRFTIME_SIZE>, DtErr> {
let mut gt = self.to_gregorian_time();
gt.set_offset(Some(0)).set_tz_abbrev(None);
let mut buf = [0u8; STRFTIME_SIZE];
let mut pos = 0usize;
gt.format_to_buffer(fmt.as_bytes(), &mut buf, &mut pos)?;
Ok(AsciiStr::from_filled_buffer(buf))
}
pub fn to_str_bin_with_offset(
&self,
fmt: &str,
secs: i32,
) -> Result<AsciiStr<STRFTIME_SIZE>, DtErr> {
let gt = self.gregorian_time_with_offset(secs);
let mut buf = [0u8; STRFTIME_SIZE];
let mut pos = 0usize;
gt.format_to_buffer(fmt.as_bytes(), &mut buf, &mut pos)?;
Ok(AsciiStr::from_filled_buffer(buf))
}
pub fn to_str_bin_with_tz(
&self,
fmt: &str,
tz_name: &str,
) -> Result<AsciiStr<STRFTIME_SIZE>, DtErr> {
let gt = self.gregorian_time_with_tz(tz_name);
let mut buf = [0u8; STRFTIME_SIZE];
let mut pos = 0usize;
gt.format_to_buffer(fmt.as_bytes(), &mut buf, &mut pos)?;
Ok(AsciiStr::from_filled_buffer(buf))
}
#[inline]
pub const fn sec_as_hhmm(seconds: i32) -> (bool, u8, u8) {
let total = seconds.abs();
let hours = (total / 3600) as u8;
let minutes = ((total % 3600) / 60) as u8;
(seconds < 0, hours, minutes)
}
pub fn to_u8_with_offset(&self, fmt: &str, dest: &mut [u8], secs: i32) -> Result<usize, DtErr> {
let gt = self.gregorian_time_with_offset(secs);
let mut internal_buf = [0u8; STRFTIME_SIZE];
let mut pos = 0usize;
gt.format_to_buffer(fmt.as_bytes(), &mut internal_buf, &mut pos)?;
let written = pos.min(dest.len());
if written > 0 {
dest[0..written].copy_from_slice(&internal_buf[0..written]);
}
Ok(written)
}
pub fn to_u8_with_tz(&self, fmt: &str, dest: &mut [u8], tz_name: &str) -> Result<usize, DtErr> {
let gt = self.gregorian_time_with_tz(tz_name);
let mut internal_buf = [0u8; STRFTIME_SIZE];
let mut pos = 0usize;
gt.format_to_buffer(fmt.as_bytes(), &mut internal_buf, &mut pos)?;
let written = pos.min(dest.len());
if written > 0 {
dest[0..written].copy_from_slice(&internal_buf[0..written]);
}
Ok(written)
}
pub(crate) fn gregorian_time_with_offset(&self, secs: i32) -> GregorianTime {
let local_tp = if secs != 0 {
*self + TSpan::new(secs as i64, 0)
} else {
*self
};
let mut gt = local_tp.to_gregorian_time();
gt.set_offset(Some(secs));
gt
}
pub(crate) fn gregorian_time_with_tz(&self, tz_name: &str) -> GregorianTime {
let utc_unix = self.to_epoch(Dt::UNIX_EPOCH, Scale::UTC).to_sec();
let (offset_secs, abbrev) = match offset_info_at_utc(tz_name, utc_unix) {
Some(info) => (info.offset, info.abbrev),
None => (0, "UTC"), };
let span = TSpan::new(offset_secs as i64, 0);
let local_tp = *self + span;
let mut gt = local_tp.to_gregorian_time();
gt.set_offset(Some(offset_secs));
gt.set_tz(Some(tz_name));
gt.set_tz_abbrev(Some(abbrev));
gt
}
}