Skip to content

Commit d3e1bfe

Browse files
Merge pull request RustPython#1141 from RustPython/time-module-fixes
Add mktime function.
2 parents aa74401 + e705ec2 commit d3e1bfe

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

vm/src/obj/objsequence.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use num_bigint::{BigInt, ToBigInt};
1111
use num_traits::{One, Signed, ToPrimitive, Zero};
1212

1313
use super::objbool;
14-
use super::objint::PyInt;
14+
use super::objint::{PyInt, PyIntRef};
1515
use super::objlist::PyList;
1616
use super::objslice::{PySlice, PySliceRef};
1717
use super::objtuple::PyTuple;
@@ -170,6 +170,31 @@ impl TryFromObject for SequenceIndex {
170170
}
171171
}
172172

173+
/// Get the index into a sequence like type. Get it from a python integer
174+
/// object, accounting for negative index, and out of bounds issues.
175+
pub fn get_sequence_index(vm: &VirtualMachine, index: &PyIntRef, length: usize) -> PyResult<usize> {
176+
if let Some(value) = index.as_bigint().to_i64() {
177+
if value < 0 {
178+
let from_end: usize = -value as usize;
179+
if from_end > length {
180+
Err(vm.new_index_error("Index out of bounds!".to_string()))
181+
} else {
182+
let index = length - from_end;
183+
Ok(index)
184+
}
185+
} else {
186+
let index = value as usize;
187+
if index >= length {
188+
Err(vm.new_index_error("Index out of bounds!".to_string()))
189+
} else {
190+
Ok(index)
191+
}
192+
}
193+
} else {
194+
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string()))
195+
}
196+
}
197+
173198
pub fn get_item(
174199
vm: &VirtualMachine,
175200
sequence: &PyObjectRef,

vm/src/stdlib/time_module.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use std::thread;
66
use std::time::{Duration, SystemTime, UNIX_EPOCH};
77

88
use crate::function::{OptionalArg, PyFuncArgs};
9+
use crate::obj::objint::PyIntRef;
10+
use crate::obj::objsequence::get_sequence_index;
911
use crate::obj::objstr::PyStringRef;
1012
use crate::obj::objtype::PyClassRef;
1113
use crate::obj::{objfloat, objint, objtype};
@@ -93,6 +95,12 @@ fn time_localtime(secs: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResu
9395
Ok(value)
9496
}
9597

98+
fn time_mktime(t: PyStructTimeRef, vm: &VirtualMachine) -> PyResult {
99+
let datetime = t.get_date_time();
100+
let seconds_since_epoch = datetime.timestamp() as f64;
101+
Ok(vm.ctx.new_float(seconds_since_epoch))
102+
}
103+
96104
/// Construct a localtime from the optional seconds, or get the current local time.
97105
fn optional_or_localtime(
98106
secs: OptionalArg<PyObjectRef>,
@@ -182,17 +190,41 @@ impl PyStructTime {
182190
fn repr(&self, _vm: &VirtualMachine) -> String {
183191
// TODO: extract year day and isdst somehow..
184192
format!(
185-
"time.struct_time(tm_year={}, tm_mon={}, tm_mday={}, tm_hour={}, tm_min={}, tm_sec={}, tm_wday={})",
193+
"time.struct_time(tm_year={}, tm_mon={}, tm_mday={}, tm_hour={}, tm_min={}, tm_sec={}, tm_wday={}, tm_yday={})",
186194
self.tm.date().year(), self.tm.date().month(), self.tm.date().day(),
187195
self.tm.time().hour(), self.tm.time().minute(), self.tm.time().second(),
188-
self.tm.date().weekday().num_days_from_monday()
196+
self.tm.date().weekday().num_days_from_monday(),
197+
self.tm.date().ordinal()
189198
)
190199
}
191200

192201
fn get_date_time(&self) -> NaiveDateTime {
193202
self.tm
194203
}
195204

205+
#[pymethod(name = "__len__")]
206+
fn len(&self, _vm: &VirtualMachine) -> usize {
207+
8
208+
}
209+
210+
#[pymethod(name = "__getitem__")]
211+
fn getitem(&self, needle: PyIntRef, vm: &VirtualMachine) -> PyResult {
212+
let index = get_sequence_index(vm, &needle, 8)?;
213+
match index {
214+
0 => Ok(vm.ctx.new_int(self.tm.date().year())),
215+
1 => Ok(vm.ctx.new_int(self.tm.date().month())),
216+
2 => Ok(vm.ctx.new_int(self.tm.date().day())),
217+
3 => Ok(vm.ctx.new_int(self.tm.time().hour())),
218+
4 => Ok(vm.ctx.new_int(self.tm.time().minute())),
219+
5 => Ok(vm.ctx.new_int(self.tm.time().second())),
220+
6 => Ok(vm
221+
.ctx
222+
.new_int(self.tm.date().weekday().num_days_from_monday())),
223+
7 => Ok(vm.ctx.new_int(self.tm.date().ordinal())),
224+
_ => unreachable!(),
225+
}
226+
}
227+
196228
#[pyproperty(name = "tm_year")]
197229
fn tm_year(&self, _vm: &VirtualMachine) -> i32 {
198230
self.tm.date().year()
@@ -227,6 +259,11 @@ impl PyStructTime {
227259
fn tm_wday(&self, _vm: &VirtualMachine) -> u32 {
228260
self.tm.date().weekday().num_days_from_monday()
229261
}
262+
263+
#[pyproperty(name = "tm_yday")]
264+
fn tm_yday(&self, _vm: &VirtualMachine) -> u32 {
265+
self.tm.date().ordinal()
266+
}
230267
}
231268

232269
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
@@ -238,6 +275,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
238275
"asctime" => ctx.new_rustfunc(time_asctime),
239276
"ctime" => ctx.new_rustfunc(time_ctime),
240277
"gmtime" => ctx.new_rustfunc(time_gmtime),
278+
"mktime" => ctx.new_rustfunc(time_mktime),
241279
"localtime" => ctx.new_rustfunc(time_localtime),
242280
"monotonic" => ctx.new_rustfunc(time_monotonic),
243281
"strftime" => ctx.new_rustfunc(time_strftime),

0 commit comments

Comments
 (0)