Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 82e73e0

Browse files
Merge pull request #817 from nicholasbishop/bishop-raw-time
Add Time to uefi-raw and use it from uefi
2 parents 0592259 + bcbe10a commit 82e73e0

File tree

3 files changed

+202
-111
lines changed

3 files changed

+202
-111
lines changed

‎uefi-raw/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod enums;
1919

2020
pub mod protocol;
2121
pub mod table;
22+
pub mod time;
2223

2324
mod status;
2425

‎uefi-raw/src/time.rs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//! Date and time types.
2+
3+
use bitflags::bitflags;
4+
use core::fmt::{self, Display, Formatter};
5+
6+
/// Date and time representation.
7+
#[derive(Debug, Default, Copy, Clone, Eq)]
8+
#[repr(C)]
9+
pub struct Time {
10+
/// Year. Valid range: `1900..=9999`.
11+
pub year: u16,
12+
13+
/// Month. Valid range: `1..=12`.
14+
pub month: u8,
15+
16+
/// Day of the month. Valid range: `1..=31`.
17+
pub day: u8,
18+
19+
/// Hour. Valid range: `0..=23`.
20+
pub hour: u8,
21+
22+
/// Minute. Valid range: `0..=59`.
23+
pub minute: u8,
24+
25+
/// Second. Valid range: `0..=59`.
26+
pub second: u8,
27+
28+
/// Unused padding.
29+
pub pad1: u8,
30+
31+
/// Nanosececond. Valid range: `0..=999_999_999`.
32+
pub nanosecond: u32,
33+
34+
/// Offset in minutes from UTC. Valid range: `-1440..=1440`, or
35+
/// [`Time::UNSPECIFIED_TIMEZONE`].
36+
pub time_zone: i16,
37+
38+
/// Daylight savings time information.
39+
pub daylight: Daylight,
40+
41+
/// Unused padding.
42+
pub pad2: u8,
43+
}
44+
45+
impl Time {
46+
/// Indicates the time should be interpreted as local time.
47+
pub const UNSPECIFIED_TIMEZONE: i16 = 0x07ff;
48+
49+
/// Create an invalid `Time` with all fields set to zero.
50+
#[must_use]
51+
pub const fn invalid() -> Self {
52+
Self {
53+
year: 0,
54+
month: 0,
55+
day: 0,
56+
hour: 0,
57+
minute: 0,
58+
second: 0,
59+
pad1: 0,
60+
nanosecond: 0,
61+
time_zone: 0,
62+
daylight: Daylight::empty(),
63+
pad2: 0,
64+
}
65+
}
66+
67+
/// True if all fields are within valid ranges, false otherwise.
68+
#[must_use]
69+
pub fn is_valid(&self) -> bool {
70+
(1900..=9999).contains(&self.year)
71+
&& (1..=12).contains(&self.month)
72+
&& (1..=31).contains(&self.day)
73+
&& self.hour <= 23
74+
&& self.minute <= 59
75+
&& self.second <= 59
76+
&& self.nanosecond <= 999_999_999
77+
&& ((-1440..=1440).contains(&self.time_zone)
78+
|| self.time_zone == Self::UNSPECIFIED_TIMEZONE)
79+
}
80+
}
81+
82+
impl Display for Time {
83+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84+
write!(f, "{:04}-{:02}-{:02} ", self.year, self.month, self.day)?;
85+
write!(
86+
f,
87+
"{:02}:{:02}:{:02}.{:09}",
88+
self.hour, self.minute, self.second, self.nanosecond
89+
)?;
90+
91+
if self.time_zone == Self::UNSPECIFIED_TIMEZONE {
92+
write!(f, " (local)")?;
93+
} else {
94+
let offset_in_hours = self.time_zone as f32 / 60.0;
95+
let integer_part = offset_in_hours as i16;
96+
// We can't use "offset_in_hours.fract()" because it is part of `std`.
97+
let fraction_part = offset_in_hours - (integer_part as f32);
98+
// most time zones
99+
if fraction_part == 0.0 {
100+
write!(f, "UTC+{offset_in_hours}")?;
101+
}
102+
// time zones with 30min offset (and perhaps other special time zones)
103+
else {
104+
write!(f, "UTC+{offset_in_hours:.1}")?;
105+
}
106+
}
107+
108+
Ok(())
109+
}
110+
}
111+
112+
/// The padding fields of `Time` are ignored for comparison.
113+
impl PartialEq for Time {
114+
fn eq(&self, other: &Time) -> bool {
115+
self.year == other.year
116+
&& self.month == other.month
117+
&& self.day == other.day
118+
&& self.hour == other.hour
119+
&& self.minute == other.minute
120+
&& self.second == other.second
121+
&& self.nanosecond == other.nanosecond
122+
&& self.time_zone == other.time_zone
123+
&& self.daylight == other.daylight
124+
}
125+
}
126+
127+
bitflags! {
128+
/// A bitmask containing daylight savings time information.
129+
#[repr(transparent)]
130+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
131+
pub struct Daylight: u8 {
132+
/// Time is affected by daylight savings time.
133+
const ADJUST_DAYLIGHT = 0x01;
134+
135+
/// Time has been adjusted for daylight savings time.
136+
const IN_DAYLIGHT = 0x02;
137+
}
138+
}
139+
140+
#[cfg(test)]
141+
mod tests {
142+
extern crate alloc;
143+
144+
use super::*;
145+
use alloc::string::ToString;
146+
147+
#[test]
148+
fn test_time_display() {
149+
let mut time = Time {
150+
year: 2023,
151+
month: 5,
152+
day: 18,
153+
hour: 11,
154+
minute: 29,
155+
second: 57,
156+
nanosecond: 123_456_789,
157+
time_zone: Time::UNSPECIFIED_TIMEZONE,
158+
daylight: Daylight::empty(),
159+
pad1: 0,
160+
pad2: 0,
161+
};
162+
assert_eq!(time.to_string(), "2023年05月18日 11:29:57.123456789 (local)");
163+
164+
time.time_zone = 120;
165+
assert_eq!(time.to_string(), "2023年05月18日 11:29:57.123456789UTC+2");
166+
167+
time.time_zone = 150;
168+
assert_eq!(time.to_string(), "2023年05月18日 11:29:57.123456789UTC+2.5");
169+
}
170+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /