Skip to content

Commit fb23cc6

Browse files
committed
Add time.ctime, time.strftime
1 parent 0ab3965 commit fb23cc6

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

tests/snippets/test_time.py

+11
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,14 @@
88
assert x.tm_min == 16
99
assert x.tm_sec == 40
1010

11+
s = time.strftime('%Y-%m-%d-%H-%M-%S', x)
12+
# print(s)
13+
assert s == '1970-01-01-00-16-40'
14+
15+
x2 = time.strptime(s, '%Y-%m-%d-%H-%M-%S')
16+
assert x2.tm_min == 16
17+
18+
s = time.asctime(x)
19+
# print(s)
20+
assert s == 'Thu Jan 1 00:16:40 1970'
21+

vm/src/stdlib/time_module.rs

+70-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use std::thread;
66
use std::time::{Duration, SystemTime, UNIX_EPOCH};
77

88
use crate::function::{OptionalArg, PyFuncArgs};
9+
use crate::obj::objstr::PyStringRef;
910
use crate::obj::objtype::PyClassRef;
1011
use crate::obj::{objfloat, objint, objtype};
11-
use crate::pyobject::{PyClassImpl, PyObjectRef, PyResult, PyValue};
12+
use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue};
1213
use crate::vm::VirtualMachine;
1314

1415
use num_traits::cast::ToPrimitive;
@@ -87,20 +88,78 @@ fn time_gmtime(secs: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<
8788
}
8889

8990
fn time_localtime(secs: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<PyStructTime> {
91+
let instant = optional_or_localtime(secs, vm)?;
92+
let value = PyStructTime::new(instant);
93+
Ok(value)
94+
}
95+
96+
/// Construct a localtime from the optional seconds, or get the current local time.
97+
fn optional_or_localtime(
98+
secs: OptionalArg<PyObjectRef>,
99+
vm: &VirtualMachine,
100+
) -> PyResult<NaiveDateTime> {
90101
let default = chrono::offset::Local::now().naive_local();
91102
let instant = match secs {
92103
OptionalArg::Present(secs) => pyobj_to_naive_date_time(&secs, vm)?.unwrap_or(default),
93104
OptionalArg::Missing => default,
94105
};
95-
let value = PyStructTime::new(instant);
96-
Ok(value)
106+
Ok(instant)
107+
}
108+
109+
const CFMT: &str = "%a %b %e %H:%M:%S %Y";
110+
111+
fn time_asctime(t: OptionalArg<PyStructTimeRef>, vm: &VirtualMachine) -> PyResult {
112+
let default = chrono::offset::Local::now().naive_local();
113+
let instant = match t {
114+
OptionalArg::Present(t) => t.get_date_time(),
115+
OptionalArg::Missing => default,
116+
};
117+
let formatted_time = instant.format(&CFMT).to_string();
118+
Ok(vm.ctx.new_str(formatted_time))
119+
}
120+
121+
fn time_ctime(secs: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<String> {
122+
let instant = optional_or_localtime(secs, vm)?;
123+
let formatted_time = instant.format(&CFMT).to_string();
124+
Ok(formatted_time)
125+
}
126+
127+
fn time_strftime(
128+
format: PyStringRef,
129+
t: OptionalArg<PyStructTimeRef>,
130+
vm: &VirtualMachine,
131+
) -> PyResult {
132+
let default = chrono::offset::Local::now().naive_local();
133+
let instant = match t {
134+
OptionalArg::Present(t) => t.get_date_time(),
135+
OptionalArg::Missing => default,
136+
};
137+
let formatted_time = instant.format(&format.value).to_string();
138+
Ok(vm.ctx.new_str(formatted_time))
139+
}
140+
141+
fn time_strptime(
142+
string: PyStringRef,
143+
format: OptionalArg<PyStringRef>,
144+
vm: &VirtualMachine,
145+
) -> PyResult<PyStructTime> {
146+
let format: String = match format {
147+
OptionalArg::Present(format) => format.value.clone(),
148+
OptionalArg::Missing => "%a %b %H:%M:%S %Y".to_string(),
149+
};
150+
let instant = NaiveDateTime::parse_from_str(&string.value, &format)
151+
.map_err(|e| vm.new_value_error(format!("Parse error: {:?}", e)))?;
152+
let struct_time = PyStructTime::new(instant);
153+
Ok(struct_time)
97154
}
98155

99156
#[pyclass(name = "struct_time")]
100157
struct PyStructTime {
101158
tm: NaiveDateTime,
102159
}
103160

161+
type PyStructTimeRef = PyRef<PyStructTime>;
162+
104163
impl fmt::Debug for PyStructTime {
105164
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106165
write!(f, "struct_time()")
@@ -130,6 +189,10 @@ impl PyStructTime {
130189
)
131190
}
132191

192+
fn get_date_time(&self) -> NaiveDateTime {
193+
self.tm
194+
}
195+
133196
#[pyproperty(name = "tm_year")]
134197
fn tm_year(&self, _vm: &VirtualMachine) -> i32 {
135198
self.tm.date().year()
@@ -172,9 +235,13 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
172235
let struct_time_type = PyStructTime::make_class(ctx);
173236

174237
py_module!(vm, "time", {
238+
"asctime" => ctx.new_rustfunc(time_asctime),
239+
"ctime" => ctx.new_rustfunc(time_ctime),
175240
"gmtime" => ctx.new_rustfunc(time_gmtime),
176241
"localtime" => ctx.new_rustfunc(time_localtime),
177242
"monotonic" => ctx.new_rustfunc(time_monotonic),
243+
"strftime" => ctx.new_rustfunc(time_strftime),
244+
"strptime" => ctx.new_rustfunc(time_strptime),
178245
"sleep" => ctx.new_rustfunc(time_sleep),
179246
"struct_time" => struct_time_type,
180247
"time" => ctx.new_rustfunc(time_time)

0 commit comments

Comments
 (0)