time: update unix time acces, fix issues related to deviating unix times (#21293)

This commit is contained in:
Turiiya 2024-04-16 23:33:37 +02:00 committed by GitHub
parent 9d117fc3a0
commit 1363cc85fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 251 additions and 193 deletions

View file

@ -82,7 +82,7 @@ jobs:
.github/workflows/retry.sh git clone --depth 1 https://github.com/vlang/ved .github/workflows/retry.sh git clone --depth 1 https://github.com/vlang/ved
cd ved && ../v -o ved . cd ved && ../v -o ved .
../v -autofree . ../v -autofree .
../v -prod . # ../v -prod . # NOTE: temporary disabled due to deprecations. Enable after resolving github.com/vlang/ved/pull/181
cd .. cd ..
- name: Build V UI examples - name: Build V UI examples
run: | run: |

View file

@ -74,7 +74,7 @@ jobs:
.github/workflows/retry.sh git clone --depth 1 https://github.com/vlang/ved .github/workflows/retry.sh git clone --depth 1 https://github.com/vlang/ved
cd ved && ../v -o ved . cd ved && ../v -o ved .
../v -autofree . ../v -autofree .
../v -prod . # ../v -prod . # NOTE: temporary disabled due to deprecations. Enable after resolving github.com/vlang/ved/pull/181
cd .. cd ..
- name: Build vlang/pdf - name: Build vlang/pdf
@ -124,8 +124,8 @@ jobs:
v install v install
echo "Build v-analyzer debug" echo "Build v-analyzer debug"
v build.vsh debug v build.vsh debug
echo "Build v-analyzer release" # echo "Build v-analyzer release"
v build.vsh release # v build.vsh release # NOTE: temporary disabled due to deprecations.
- name: Format vlang/v-analyzer - name: Format vlang/v-analyzer
run: | run: |

View file

@ -1590,7 +1590,7 @@ fn main() {
month: 12 month: 12
day: 25 day: 25
} }
println(time.new_time(my_time).utc_string()) println(time.new(my_time).utc_string())
println('Century: ${my_time.century()}') println('Century: ${my_time.century()}')
} }
``` ```

View file

@ -733,7 +733,7 @@ fn (mut app App) handle_swipe() {
adx, ady := math.abs(dx), math.abs(dy) adx, ady := math.abs(dx), math.abs(dy)
dmin := if math.min(adx, ady) > 0 { math.min(adx, ady) } else { 1 } dmin := if math.min(adx, ady) > 0 { math.min(adx, ady) } else { 1 }
dmax := if math.max(adx, ady) > 0 { math.max(adx, ady) } else { 1 } dmax := if math.max(adx, ady) > 0 { math.max(adx, ady) } else { 1 }
tdiff := int(e.time.unix_time_milli() - s.time.unix_time_milli()) tdiff := int(e.time.unix_milli() - s.time.unix_milli())
// TODO: make this calculation more accurate (don't use arbitrary numbers) // TODO: make this calculation more accurate (don't use arbitrary numbers)
min_swipe_distance := int(math.sqrt(math.min(w, h) * tdiff / 100)) + 20 min_swipe_distance := int(math.sqrt(math.min(w, h) * tdiff / 100)) + 20
if dmax < min_swipe_distance { if dmax < min_swipe_distance {

View file

@ -43,13 +43,13 @@ pub fn (octx OneContext) deadline() ?time.Time {
for ctx in octx.ctxs { for ctx in octx.ctxs {
if deadline := ctx.deadline() { if deadline := ctx.deadline() {
if min.unix_time() == 0 || deadline < min { if min.unix() == 0 || deadline < min {
min = deadline min = deadline
} }
} }
} }
if min.unix_time() == 0 { if min.unix() == 0 {
return none return none
} }

View file

@ -95,7 +95,7 @@ fn test_merge_deadline_context_1() {
mut ctx, _ := merge(ctx1, ctx2) mut ctx, _ := merge(ctx1, ctx2)
if deadline := ctx.deadline() { if deadline := ctx.deadline() {
assert deadline.unix_time() != 0 assert deadline.unix() != 0
} else { } else {
assert false assert false
} }
@ -111,7 +111,7 @@ fn test_merge_deadline_context_2() {
mut ctx, _ := merge(ctx1, ctx2) mut ctx, _ := merge(ctx1, ctx2)
if deadline := ctx.deadline() { if deadline := ctx.deadline() {
assert deadline.unix_time() != 0 assert deadline.unix() != 0
} else { } else {
assert false assert false
} }

View file

@ -244,7 +244,7 @@ fn stmt_bind_primitive(mut stmt Stmt, data orm.Primitive) {
stmt.bind_text(data) stmt.bind_text(data)
} }
time.Time { time.Time {
unix := int(data.unix) unix := int(data.unix())
stmt_bind_primitive(mut stmt, unix) stmt_bind_primitive(mut stmt, unix)
} }
orm.InfixType { orm.InfixType {

View file

@ -140,7 +140,7 @@ fn bind(stmt Stmt, c &int, data orm.Primitive) int {
err = stmt.bind_text(c, data) err = stmt.bind_text(c, data)
} }
time.Time { time.Time {
err = stmt.bind_int(c, int(data.unix)) err = stmt.bind_int(c, int(data.unix()))
} }
orm.InfixType { orm.InfixType {
err = bind(stmt, c, data.right) err = bind(stmt, c, data.right)

View file

@ -95,7 +95,7 @@ fn test_encode_decode_sumtype() {
enc := json.encode(game) enc := json.encode(game)
// eprintln('Encoded Game: $enc') // eprintln('Encoded Game: $enc')
assert enc == '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},"cat","Stool",{"_type":"Time","value":${t.unix_time()}}]}' assert enc == '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},"cat","Stool",{"_type":"Time","value":${t.unix()}}]}'
dec := json.decode(SomeGame, enc)! dec := json.decode(SomeGame, enc)!
// eprintln('Decoded Game: $dec') // eprintln('Decoded Game: $dec')
@ -104,7 +104,7 @@ fn test_encode_decode_sumtype() {
assert game.player == dec.player assert game.player == dec.player
assert (game.other[2] as Animal) == .cat assert (game.other[2] as Animal) == .cat
assert dec.other[2] == Entity('cat') assert dec.other[2] == Entity('cat')
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time() assert (game.other[4] as time.Time).unix() == (dec.other[4] as time.Time).unix()
} }
fn bar[T](payload string) !Bar { // ?T doesn't work currently fn bar[T](payload string) !Bar { // ?T doesn't work currently
@ -156,7 +156,7 @@ fn test_parse_user() {
fn test_encode_decode_time() { fn test_encode_decode_time() {
user := User2{ user := User2{
age: 25 age: 25
reg_date: time.new_time(year: 2020, month: 12, day: 22, hour: 7, minute: 23) reg_date: time.new(year: 2020, month: 12, day: 22, hour: 7, minute: 23)
} }
s := json.encode(user) s := json.encode(user)
// println(s) // println(s)

View file

@ -4,9 +4,7 @@ import time
// no_deadline should be given to functions when no deadline is wanted (i.e. all functions // no_deadline should be given to functions when no deadline is wanted (i.e. all functions
// return instantly) // return instantly)
const no_deadline = time.Time{ const no_deadline = time.unix(0)
unix: 0
}
// no_timeout should be given to functions when no timeout is wanted (i.e. all functions // no_timeout should be given to functions when no timeout is wanted (i.e. all functions
// return instantly) // return instantly)
@ -148,7 +146,7 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
@[inline] @[inline]
fn select_deadline(handle int, test Select, deadline time.Time) !bool { fn select_deadline(handle int, test Select, deadline time.Time) !bool {
// if we have a 0 deadline here then the timeout that was passed was infinite... // if we have a 0 deadline here then the timeout that was passed was infinite...
infinite := deadline.unix_time() == 0 infinite := deadline.unix() == 0
for infinite || time.now() <= deadline { for infinite || time.now() <= deadline {
timeout := if infinite { net.infinite_timeout } else { deadline - time.now() } timeout := if infinite { net.infinite_timeout } else { deadline - time.now() }
ready := @select(handle, test, timeout) or { ready := @select(handle, test, timeout) or {

View file

@ -120,7 +120,7 @@ fn (mut s SSLConn) init() ! {
mut cert := s.config.cert mut cert := s.config.cert
mut cert_key := s.config.cert_key mut cert_key := s.config.cert_key
if s.config.in_memory_verification { if s.config.in_memory_verification {
now := time.now().unix.str() now := time.now().unix().str()
verify = os.temp_dir() + '/v_verify' + now verify = os.temp_dir() + '/v_verify' + now
cert = os.temp_dir() + '/v_cert' + now cert = os.temp_dir() + '/v_cert' + now
cert_key = os.temp_dir() + '/v_cert_key' + now cert_key = os.temp_dir() + '/v_cert_key' + now

View file

@ -180,7 +180,7 @@ pub fn (c TcpConn) read(mut buf []u8) !int {
} }
pub fn (mut c TcpConn) read_deadline() !time.Time { pub fn (mut c TcpConn) read_deadline() !time.Time {
if c.read_deadline.unix == 0 { if c.read_deadline.unix() == 0 {
return c.read_deadline return c.read_deadline
} }
return error('none') return error('none')
@ -245,7 +245,7 @@ pub fn (mut c TcpConn) set_read_deadline(deadline time.Time) {
} }
pub fn (mut c TcpConn) write_deadline() !time.Time { pub fn (mut c TcpConn) write_deadline() !time.Time {
if c.write_deadline.unix == 0 { if c.write_deadline.unix() == 0 {
return c.write_deadline return c.write_deadline
} }
return error('none') return error('none')
@ -448,7 +448,7 @@ pub fn (mut l TcpListener) accept_only() !&TcpConn {
} }
pub fn (c &TcpListener) accept_deadline() !time.Time { pub fn (c &TcpListener) accept_deadline() !time.Time {
if c.accept_deadline.unix != 0 { if c.accept_deadline.unix() != 0 {
return c.accept_deadline return c.accept_deadline
} }
return error('invalid deadline') return error('invalid deadline')

View file

@ -122,7 +122,7 @@ pub fn (mut c UdpConn) read(mut buf []u8) !(int, Addr) {
} }
pub fn (c &UdpConn) read_deadline() !time.Time { pub fn (c &UdpConn) read_deadline() !time.Time {
if c.read_deadline.unix == 0 { if c.read_deadline.unix() == 0 {
return c.read_deadline return c.read_deadline
} }
return error('none') return error('none')
@ -133,7 +133,7 @@ pub fn (mut c UdpConn) set_read_deadline(deadline time.Time) {
} }
pub fn (c &UdpConn) write_deadline() !time.Time { pub fn (c &UdpConn) write_deadline() !time.Time {
if c.write_deadline.unix == 0 { if c.write_deadline.unix() == 0 {
return c.write_deadline return c.write_deadline
} }
return error('none') return error('none')

View file

@ -5,9 +5,7 @@ import net
// no_deadline should be given to functions when no deadline is wanted (i.e. all functions // no_deadline should be given to functions when no deadline is wanted (i.e. all functions
// return instantly) // return instantly)
const no_deadline = time.Time{ const no_deadline = time.unix(0)
unix: 0
}
// no_timeout should be given to functions when no timeout is wanted (i.e. all functions // no_timeout should be given to functions when no timeout is wanted (i.e. all functions
// return instantly) // return instantly)
const no_timeout = time.Duration(0) const no_timeout = time.Duration(0)
@ -71,7 +69,7 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
@[inline] @[inline]
fn select_deadline(handle int, test Select, deadline time.Time) !bool { fn select_deadline(handle int, test Select, deadline time.Time) !bool {
// if we have a 0 deadline here then the timeout that was passed was infinite... // if we have a 0 deadline here then the timeout that was passed was infinite...
infinite := deadline.unix_time() == 0 infinite := deadline.unix() == 0
for infinite || time.now() <= deadline { for infinite || time.now() <= deadline {
timeout := if infinite { net.infinite_timeout } else { deadline - time.now() } timeout := if infinite { net.infinite_timeout } else { deadline - time.now() }
ready := @select(handle, test, timeout) or { ready := @select(handle, test, timeout) or {

View file

@ -152,7 +152,7 @@ pub fn (mut c StreamConn) read(mut buf []u8) !int {
// read_deadline returns the read deadline // read_deadline returns the read deadline
pub fn (mut c StreamConn) read_deadline() !time.Time { pub fn (mut c StreamConn) read_deadline() !time.Time {
if c.read_deadline.unix == 0 { if c.read_deadline.unix() == 0 {
return c.read_deadline return c.read_deadline
} }
return error('none') return error('none')
@ -165,7 +165,7 @@ pub fn (mut c StreamConn) set_read_deadline(deadline time.Time) {
// write_deadline returns the write deadline // write_deadline returns the write deadline
pub fn (mut c StreamConn) write_deadline() !time.Time { pub fn (mut c StreamConn) write_deadline() !time.Time {
if c.write_deadline.unix == 0 { if c.write_deadline.unix() == 0 {
return c.write_deadline return c.write_deadline
} }
return error('none') return error('none')
@ -297,7 +297,7 @@ pub fn (mut l StreamListener) accept() !&StreamConn {
// accept_deadline returns the deadline until a new client is accepted // accept_deadline returns the deadline until a new client is accepted
pub fn (l &StreamListener) accept_deadline() !time.Time { pub fn (l &StreamListener) accept_deadline() !time.Time {
if l.accept_deadline.unix != 0 { if l.accept_deadline.unix() != 0 {
return l.accept_deadline return l.accept_deadline
} }
return error('no deadline') return error('no deadline')

View file

@ -171,7 +171,7 @@ pub fn (mut ws Client) listen() ! {
} }
.pong { .pong {
ws.debug_log('read: pong') ws.debug_log('read: pong')
ws.last_pong_ut = time.now().unix ws.last_pong_ut = time.now().unix()
ws.send_message_event(msg) ws.send_message_event(msg)
if msg.payload.len > 0 { if msg.payload.len > 0 {
unsafe { msg.free() } unsafe { msg.free() }

View file

@ -108,7 +108,7 @@ fn (mut s Server) handle_ping() {
} }
clients_to_remove << c.client.id clients_to_remove << c.client.id
} }
if (time.now().unix - c.client.last_pong_ut) > s.get_ping_interval() * 2 { if (time.now().unix() - c.client.last_pong_ut) > s.get_ping_interval() * 2 {
clients_to_remove << c.client.id clients_to_remove << c.client.id
c.client.close(1000, 'no pong received') or { continue } c.client.close(1000, 'no pong received') or { continue }
} }
@ -150,7 +150,7 @@ pub fn (mut s Server) handle_handshake(mut conn net.TcpConn, key string) !&Serve
client_state: ClientState{ client_state: ClientState{
state: .open state: .open
} }
last_pong_ut: time.now().unix last_pong_ut: time.now().unix()
id: rand.uuid_v4() id: rand.uuid_v4()
} }
mut server_client := &ServerClient{ mut server_client := &ServerClient{
@ -225,7 +225,7 @@ fn (mut s Server) accept_new_client() !&Client {
client_state: ClientState{ client_state: ClientState{
state: .open state: .open
} }
last_pong_ut: time.now().unix last_pong_ut: time.now().unix()
id: rand.uuid_v4() id: rand.uuid_v4()
} }
return c return c

View file

@ -363,7 +363,7 @@ fn test_orm() {
}! }!
assert data.len == 1 assert data.len == 1
assert tnow.unix == data[0].create.unix assert tnow.unix() == data[0].create.unix()
mod := Module{} mod := Module{}

View file

@ -42,13 +42,13 @@ fn test_environ() {
} }
fn test_setenv_var_not_exists() { fn test_setenv_var_not_exists() {
key := time.new_time(time.now()).unix key := time.new(time.now()).unix()
os.setenv('foo${key}', 'bar', false) os.setenv('foo${key}', 'bar', false)
assert os.getenv('foo${key}') == 'bar' assert os.getenv('foo${key}') == 'bar'
} }
fn test_getenv_empty_var() { fn test_getenv_empty_var() {
key := time.new_time(time.now()).unix key := time.new(time.now()).unix()
os.setenv('empty${key}', '""', false) os.setenv('empty${key}', '""', false)
assert os.getenv('empty${key}') == '""' assert os.getenv('empty${key}') == '""'
} }

View file

@ -22,13 +22,13 @@ fn test_stat() {
mut fstat := os.stat(test_file)! mut fstat := os.stat(test_file)!
eprintln(@LOCATION) eprintln(@LOCATION)
eprintln(' | start_time: ${start_time.unix}\n | end_time: ${end_time.unix}\n | fstat.ctime: ${fstat.ctime}\n | fstat.mtime: ${fstat.mtime}') eprintln(' | start_time: ${start_time.unix()}\n | end_time: ${end_time.unix()}\n | fstat.ctime: ${fstat.ctime}\n | fstat.mtime: ${fstat.mtime}')
assert fstat.get_filetype() == .regular assert fstat.get_filetype() == .regular
assert fstat.size == u64(test_content.len) assert fstat.size == u64(test_content.len)
assert fstat.ctime >= start_time.unix assert fstat.ctime >= start_time.unix()
assert fstat.ctime <= end_time.unix assert fstat.ctime <= end_time.unix()
assert fstat.mtime >= start_time.unix assert fstat.mtime >= start_time.unix()
assert fstat.mtime <= end_time.unix assert fstat.mtime <= end_time.unix()
$if !windows { $if !windows {
os.chmod(test_file, 0o600)! os.chmod(test_file, 0o600)!

View file

@ -869,8 +869,8 @@ fn test_utime() {
os.rm(filename) or { panic(err) } os.rm(filename) or { panic(err) }
} }
f.write_string(hello) or { panic(err) } f.write_string(hello) or { panic(err) }
atime := time.now().add_days(2).unix_time() atime := time.now().add_days(2).unix()
mtime := time.now().add_days(4).unix_time() mtime := time.now().add_days(4).unix()
os.utime(filename, int(atime), int(mtime)) or { panic(err) } os.utime(filename, int(atime), int(mtime)) or { panic(err) }
assert os.file_last_mod_unix(filename) == mtime assert os.file_last_mod_unix(filename) == mtime
} }

View file

@ -323,10 +323,10 @@ pub fn (mut rng PRNG) f64_in_range(min f64, max f64) !f64 {
// users or business transactions. // users or business transactions.
// (https://news.ycombinator.com/item?id=14526173) // (https://news.ycombinator.com/item?id=14526173)
pub fn (mut rng PRNG) ulid() string { pub fn (mut rng PRNG) ulid() string {
return internal_ulid_at_millisecond(mut rng, u64(time.utc().unix_time_milli())) return internal_ulid_at_millisecond(mut rng, u64(time.utc().unix_milli()))
} }
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`. // ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_milli`.
pub fn (mut rng PRNG) ulid_at_millisecond(unix_time_milli u64) string { pub fn (mut rng PRNG) ulid_at_millisecond(unix_time_milli u64) string {
return internal_ulid_at_millisecond(mut rng, unix_time_milli) return internal_ulid_at_millisecond(mut rng, unix_time_milli)
} }
@ -671,7 +671,7 @@ pub fn ulid() string {
return default_rng.ulid() return default_rng.ulid()
} }
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`. // ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_milli`.
pub fn ulid_at_millisecond(unix_time_milli u64) string { pub fn ulid_at_millisecond(unix_time_milli u64) string {
return default_rng.ulid_at_millisecond(unix_time_milli) return default_rng.ulid_at_millisecond(unix_time_milli)
} }

View file

@ -41,7 +41,7 @@ fn test_ulids_max_start_character_is_ok() {
} }
fn test_ulids_generated_in_the_same_millisecond_have_the_same_prefix() { fn test_ulids_generated_in_the_same_millisecond_have_the_same_prefix() {
t := u64(time.utc().unix_time_milli()) t := u64(time.utc().unix_milli())
mut ulid1 := '' mut ulid1 := ''
mut ulid2 := '' mut ulid2 := ''
mut ulid3 := '' mut ulid3 := ''

View file

@ -53,7 +53,7 @@ import time
s := '2018-01-27 12:48:34' s := '2018-01-27 12:48:34'
t := time.parse(s) or { panic('failing format: ${s} | err: ${err}') } t := time.parse(s) or { panic('failing format: ${s} | err: ${err}') }
println(t) println(t)
println(t.unix) println(t.unix())
``` ```
V's time module also has these parse methods: V's time module also has these parse methods:

View file

@ -304,7 +304,7 @@ fn (mut p DateTimeParser) parse() !Time {
return error_invalid_time(0, '${month_name} has only 30 days') return error_invalid_time(0, '${month_name} has only 30 days')
} }
return new_time( return new(
year: year_ year: year_
month: month_ month: month_
day: day_in_month day: day_in_month

View file

@ -151,12 +151,9 @@ pub fn (t Time) format_rfc3339() string {
unsafe { buf.free() } unsafe { buf.free() }
} }
if t.unix == 0 && t.nanosecond == 0 { t_ := time_with_unix(t)
return buf.bytestr() if t_.is_local {
} utc_time := t_.local_to_utc()
if t.is_local {
utc_time := t.local_to_utc()
int_to_byte_array_no_pad(utc_time.year, mut buf, 4) int_to_byte_array_no_pad(utc_time.year, mut buf, 4)
int_to_byte_array_no_pad(utc_time.month, mut buf, 7) int_to_byte_array_no_pad(utc_time.month, mut buf, 7)
int_to_byte_array_no_pad(utc_time.day, mut buf, 10) int_to_byte_array_no_pad(utc_time.day, mut buf, 10)
@ -165,13 +162,13 @@ pub fn (t Time) format_rfc3339() string {
int_to_byte_array_no_pad(utc_time.second, mut buf, 19) int_to_byte_array_no_pad(utc_time.second, mut buf, 19)
int_to_byte_array_no_pad(utc_time.nanosecond / 1_000_000, mut buf, 23) int_to_byte_array_no_pad(utc_time.nanosecond / 1_000_000, mut buf, 23)
} else { } else {
int_to_byte_array_no_pad(t.year, mut buf, 4) int_to_byte_array_no_pad(t_.year, mut buf, 4)
int_to_byte_array_no_pad(t.month, mut buf, 7) int_to_byte_array_no_pad(t_.month, mut buf, 7)
int_to_byte_array_no_pad(t.day, mut buf, 10) int_to_byte_array_no_pad(t_.day, mut buf, 10)
int_to_byte_array_no_pad(t.hour, mut buf, 13) int_to_byte_array_no_pad(t_.hour, mut buf, 13)
int_to_byte_array_no_pad(t.minute, mut buf, 16) int_to_byte_array_no_pad(t_.minute, mut buf, 16)
int_to_byte_array_no_pad(t.second, mut buf, 19) int_to_byte_array_no_pad(t_.second, mut buf, 19)
int_to_byte_array_no_pad(t.nanosecond / 1_000_000, mut buf, 23) int_to_byte_array_no_pad(t_.nanosecond / 1_000_000, mut buf, 23)
} }
return buf.bytestr() return buf.bytestr()
@ -187,12 +184,9 @@ pub fn (t Time) format_rfc3339_nano() string {
unsafe { buf.free() } unsafe { buf.free() }
} }
if t.unix == 0 && t.nanosecond == 0 { t_ := time_with_unix(t)
return buf.bytestr() if t_.is_local {
} utc_time := t_.local_to_utc()
if t.is_local {
utc_time := t.local_to_utc()
int_to_byte_array_no_pad(utc_time.year, mut buf, 4) int_to_byte_array_no_pad(utc_time.year, mut buf, 4)
int_to_byte_array_no_pad(utc_time.month, mut buf, 7) int_to_byte_array_no_pad(utc_time.month, mut buf, 7)
int_to_byte_array_no_pad(utc_time.day, mut buf, 10) int_to_byte_array_no_pad(utc_time.day, mut buf, 10)
@ -201,13 +195,13 @@ pub fn (t Time) format_rfc3339_nano() string {
int_to_byte_array_no_pad(utc_time.second, mut buf, 19) int_to_byte_array_no_pad(utc_time.second, mut buf, 19)
int_to_byte_array_no_pad(utc_time.nanosecond, mut buf, 29) int_to_byte_array_no_pad(utc_time.nanosecond, mut buf, 29)
} else { } else {
int_to_byte_array_no_pad(t.year, mut buf, 4) int_to_byte_array_no_pad(t_.year, mut buf, 4)
int_to_byte_array_no_pad(t.month, mut buf, 7) int_to_byte_array_no_pad(t_.month, mut buf, 7)
int_to_byte_array_no_pad(t.day, mut buf, 10) int_to_byte_array_no_pad(t_.day, mut buf, 10)
int_to_byte_array_no_pad(t.hour, mut buf, 13) int_to_byte_array_no_pad(t_.hour, mut buf, 13)
int_to_byte_array_no_pad(t.minute, mut buf, 16) int_to_byte_array_no_pad(t_.minute, mut buf, 16)
int_to_byte_array_no_pad(t.second, mut buf, 19) int_to_byte_array_no_pad(t_.second, mut buf, 19)
int_to_byte_array_no_pad(t.nanosecond, mut buf, 29) int_to_byte_array_no_pad(t_.nanosecond, mut buf, 29)
} }
return buf.bytestr() return buf.bytestr()

View file

@ -3,7 +3,7 @@ module misc
import rand import rand
import time import time
const start_time_unix = time.now().unix const start_time_unix = time.now().unix()
// random returns a random time struct in *the past*. // random returns a random time struct in *the past*.
pub fn random() time.Time { pub fn random() time.Time {

View file

@ -8,10 +8,10 @@ fn test_random() {
t2 := tmisc.random() t2 := tmisc.random()
t3 := tmisc.random() t3 := tmisc.random()
t4 := tmisc.random() t4 := tmisc.random()
assert t1.unix != t2.unix assert t1.unix() != t2.unix()
assert t1.unix != t3.unix assert t1.unix() != t3.unix()
assert t1.unix != t4.unix assert t1.unix() != t4.unix()
assert t2.unix != t3.unix assert t2.unix() != t3.unix()
assert t2.unix != t4.unix assert t2.unix() != t4.unix()
assert t3.unix != t4.unix assert t3.unix() != t4.unix()
} }

View file

@ -3,13 +3,13 @@ module time
// operator `==` returns true if provided time is equal to time // operator `==` returns true if provided time is equal to time
@[inline] @[inline]
pub fn (t1 Time) == (t2 Time) bool { pub fn (t1 Time) == (t2 Time) bool {
return t1.unix == t2.unix && t1.nanosecond == t2.nanosecond return t1.unix() == t2.unix() && t1.nanosecond == t2.nanosecond
} }
// operator `<` returns true if provided time is less than time // operator `<` returns true if provided time is less than time
@[inline] @[inline]
pub fn (t1 Time) < (t2 Time) bool { pub fn (t1 Time) < (t2 Time) bool {
return t1.unix < t2.unix || (t1.unix == t2.unix && t1.nanosecond < t2.nanosecond) return t1.unix() < t2.unix() || (t1.unix() == t2.unix() && t1.nanosecond < t2.nanosecond)
} }
// Time subtract using operator overloading. // Time subtract using operator overloading.
@ -18,7 +18,7 @@ pub fn (lhs Time) - (rhs Time) Duration {
// lhs.unix * 1_000_000_000 + i64(lhs.nanosecond) will overflow i64, for years > 3000 . // lhs.unix * 1_000_000_000 + i64(lhs.nanosecond) will overflow i64, for years > 3000 .
// Doing the diff first, and *then* multiplying by `second`, is less likely to overflow, // Doing the diff first, and *then* multiplying by `second`, is less likely to overflow,
// since lhs and rhs will be likely close to each other. // since lhs and rhs will be likely close to each other.
unixs := i64(lhs.unix - rhs.unix) * second unixs := i64(lhs.unix() - rhs.unix()) * second
nanos := lhs.nanosecond - rhs.nanosecond nanos := lhs.nanosecond - rhs.nanosecond
return unixs + nanos return unixs + nanos
} }

View file

@ -32,7 +32,7 @@ fn test_now_always_results_in_greater_time() {
} }
fn test_time1_should_be_same_as_time2() { fn test_time1_should_be_same_as_time2() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -41,7 +41,7 @@ fn test_time1_should_be_same_as_time2() {
second: 3 second: 3
nanosecond: 100 nanosecond: 100
}) })
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -54,7 +54,7 @@ fn test_time1_should_be_same_as_time2() {
} }
fn test_time1_should_not_be_same_as_time2() { fn test_time1_should_not_be_same_as_time2() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -64,7 +64,7 @@ fn test_time1_should_not_be_same_as_time2() {
nanosecond: 100 nanosecond: 100
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -73,7 +73,7 @@ fn test_time1_should_not_be_same_as_time2() {
second: 3 second: 3
nanosecond: 101 nanosecond: 101
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -83,7 +83,7 @@ fn test_time1_should_not_be_same_as_time2() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -97,7 +97,7 @@ fn test_time1_should_not_be_same_as_time2() {
} }
fn test_time1_should_be_greater_than_time2() { fn test_time1_should_be_greater_than_time2() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -107,7 +107,7 @@ fn test_time1_should_be_greater_than_time2() {
nanosecond: 102 nanosecond: 102
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -116,7 +116,7 @@ fn test_time1_should_be_greater_than_time2() {
second: 3 second: 3
nanosecond: 101 nanosecond: 101
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -126,7 +126,7 @@ fn test_time1_should_be_greater_than_time2() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -140,7 +140,7 @@ fn test_time1_should_be_greater_than_time2() {
} }
fn test_time2_should_be_less_than_time1() { fn test_time2_should_be_less_than_time1() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -150,7 +150,7 @@ fn test_time2_should_be_less_than_time1() {
nanosecond: 102 nanosecond: 102
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -159,7 +159,7 @@ fn test_time2_should_be_less_than_time1() {
second: 3 second: 3
nanosecond: 101 nanosecond: 101
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -169,7 +169,7 @@ fn test_time2_should_be_less_than_time1() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -183,7 +183,7 @@ fn test_time2_should_be_less_than_time1() {
} }
fn test_time1_should_be_greater_or_equal_to_time2_when_gt() { fn test_time1_should_be_greater_or_equal_to_time2_when_gt() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -193,7 +193,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_gt() {
nanosecond: 102 nanosecond: 102
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -202,7 +202,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_gt() {
second: 3 second: 3
nanosecond: 101 nanosecond: 101
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -212,7 +212,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_gt() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -226,7 +226,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_gt() {
} }
fn test_time1_should_be_greater_or_equal_to_time2_when_eq() { fn test_time1_should_be_greater_or_equal_to_time2_when_eq() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -236,7 +236,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_eq() {
nanosecond: 100 nanosecond: 100
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -245,7 +245,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_eq() {
second: 3 second: 3
nanosecond: 100 nanosecond: 100
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -255,7 +255,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_eq() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -269,7 +269,7 @@ fn test_time1_should_be_greater_or_equal_to_time2_when_eq() {
} }
fn test_time1_should_be_less_or_equal_to_time2_when_lt() { fn test_time1_should_be_less_or_equal_to_time2_when_lt() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -279,7 +279,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_lt() {
nanosecond: 100 nanosecond: 100
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -288,7 +288,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_lt() {
second: 3 second: 3
nanosecond: 101 nanosecond: 101
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -298,7 +298,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_lt() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -312,7 +312,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_lt() {
} }
fn test_time1_should_be_less_or_equal_to_time2_when_eq() { fn test_time1_should_be_less_or_equal_to_time2_when_eq() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -322,7 +322,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_eq() {
nanosecond: 100 nanosecond: 100
}) })
// Difference is one nanosecond // Difference is one nanosecond
t2 := new_time(Time{ t2 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -331,7 +331,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_eq() {
second: 3 second: 3
nanosecond: 100 nanosecond: 100
}) })
t3 := new_time(Time{ t3 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -341,7 +341,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_eq() {
nanosecond: 0 nanosecond: 0
}) })
// Difference is one second // Difference is one second
t4 := new_time(Time{ t4 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -355,7 +355,7 @@ fn test_time1_should_be_less_or_equal_to_time2_when_eq() {
} }
fn test_time2_copied_from_time1_should_be_equal() { fn test_time2_copied_from_time1_should_be_equal() {
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10
@ -364,7 +364,7 @@ fn test_time2_copied_from_time1_should_be_equal() {
second: 3 second: 3
nanosecond: 100 nanosecond: 100
}) })
t2 := new_time(t1) t2 := new(t1)
assert t2 == t1 assert t2 == t1
} }
@ -372,7 +372,7 @@ fn test_subtract() {
d_seconds := 3 d_seconds := 3
d_nanoseconds := 13 d_nanoseconds := 13
duration := d_seconds * second + d_nanoseconds * nanosecond duration := d_seconds * second + d_nanoseconds * nanosecond
t1 := new_time(Time{ t1 := new(Time{
year: 2000 year: 2000
month: 5 month: 5
day: 10 day: 10

View file

@ -26,7 +26,7 @@ pub fn parse_rfc3339(s string) !Time {
// Check if sn is date only // Check if sn is date only
if !parts[0].contains_any(' Z') && parts[0].contains('-') { if !parts[0].contains_any(' Z') && parts[0].contains('-') {
year, month, day := parse_iso8601_date(sn)! year, month, day := parse_iso8601_date(sn)!
t = new_time(Time{ t = new(Time{
year: year year: year
month: month month: month
day: day day: day
@ -37,7 +37,7 @@ pub fn parse_rfc3339(s string) !Time {
if !parts[0].contains('-') && parts[0].contains(':') { if !parts[0].contains('-') && parts[0].contains(':') {
mut hour_, mut minute_, mut second_, mut microsecond_, mut nanosecond_, mut unix_offset, mut is_local_time := 0, 0, 0, 0, 0, i64(0), true mut hour_, mut minute_, mut second_, mut microsecond_, mut nanosecond_, mut unix_offset, mut is_local_time := 0, 0, 0, 0, 0, i64(0), true
hour_, minute_, second_, microsecond_, nanosecond_, unix_offset, is_local_time = parse_iso8601_time(parts[0])! hour_, minute_, second_, microsecond_, nanosecond_, unix_offset, is_local_time = parse_iso8601_time(parts[0])!
t = new_time(Time{ t = new(Time{
hour: hour_ hour: hour_
minute: minute_ minute: minute_
second: second_ second: second_
@ -119,7 +119,7 @@ pub fn parse(s string) !Time {
if isecond > 59 || isecond < 0 { if isecond > 59 || isecond < 0 {
return error_invalid_time(8, 'seconds must be between 0 and 60') return error_invalid_time(8, 'seconds must be between 0 and 60')
} }
res := new_time(Time{ res := new(Time{
year: iyear year: iyear
month: imonth month: imonth
day: iday day: iday
@ -176,7 +176,7 @@ pub fn parse_iso8601(s string) !Time {
if parts.len == 2 { if parts.len == 2 {
hour_, minute_, second_, microsecond_, nanosecond_, unix_offset, is_local_time = parse_iso8601_time(parts[1])! hour_, minute_, second_, microsecond_, nanosecond_, unix_offset, is_local_time = parse_iso8601_time(parts[1])!
} }
mut t := new_time( mut t := new(
year: year year: year
month: month month: month
day: day day: day

View file

@ -9,7 +9,7 @@ fn test_parse() {
} }
assert t.year == 2018 && t.month == 1 && t.day == 27 && t.hour == 12 && t.minute == 48 assert t.year == 2018 && t.month == 1 && t.day == 27 && t.hour == 12 && t.minute == 48
&& t.second == 34 && t.second == 34
assert t.unix == 1517057314 assert t.unix() == 1517057314
} }
fn test_parse_invalid() { fn test_parse_invalid() {
@ -33,7 +33,7 @@ fn test_parse_rfc2822() {
} }
assert t1.year == 2019 && t1.month == 12 && t1.day == 12 && t1.hour == 6 && t1.minute == 7 assert t1.year == 2019 && t1.month == 12 && t1.day == 12 && t1.hour == 6 && t1.minute == 7
&& t1.second == 45 && t1.second == 45
assert t1.unix == 1576130865 assert t1.unix() == 1576130865
s2 := 'Thu 12 Dec 2019 06:07:45 +0800' s2 := 'Thu 12 Dec 2019 06:07:45 +0800'
t2 := time.parse_rfc2822(s2) or { t2 := time.parse_rfc2822(s2) or {
eprintln('> failing format: ${s2} | err: ${err}') eprintln('> failing format: ${s2} | err: ${err}')
@ -42,7 +42,7 @@ fn test_parse_rfc2822() {
} }
assert t2.year == 2019 && t2.month == 12 && t2.day == 12 && t2.hour == 6 && t2.minute == 7 assert t2.year == 2019 && t2.month == 12 && t2.day == 12 && t2.hour == 6 && t2.minute == 7
&& t2.second == 45 && t2.second == 45
assert t2.unix == 1576130865 assert t2.unix() == 1576130865
} }
fn test_parse_rfc2822_invalid() { fn test_parse_rfc2822_invalid() {
@ -192,14 +192,14 @@ fn test_ad_second_to_parse_result_in_2001() {
now_tm := time.parse('2001-01-01 04:00:00')! now_tm := time.parse('2001-01-01 04:00:00')!
future_tm := now_tm.add_seconds(60) future_tm := now_tm.add_seconds(60)
assert future_tm.str() == '2001-01-01 04:01:00' assert future_tm.str() == '2001-01-01 04:01:00'
assert now_tm.unix < future_tm.unix assert now_tm.unix() < future_tm.unix()
} }
fn test_ad_second_to_parse_result_pre_2001() { fn test_ad_second_to_parse_result_pre_2001() {
now_tm := time.parse('2000-01-01 04:00:00')! now_tm := time.parse('2000-01-01 04:00:00')!
future_tm := now_tm.add_seconds(60) future_tm := now_tm.add_seconds(60)
assert future_tm.str() == '2000-01-01 04:01:00' assert future_tm.str() == '2000-01-01 04:01:00'
assert now_tm.unix < future_tm.unix assert now_tm.unix() < future_tm.unix()
} }
fn test_parse_format() { fn test_parse_format() {

View file

@ -57,7 +57,13 @@ pub fn utc() Time {
} }
// new_time returns a time struct with the calculated Unix time. // new_time returns a time struct with the calculated Unix time.
@[deprecated: 'use `new()` instead']
@[deprecated_after: '2024-05-31']
pub fn new_time(t Time) Time { pub fn new_time(t Time) Time {
return time_with_unix(t)
}
fn time_with_unix(t Time) Time {
if t.unix != 0 { if t.unix != 0 {
return t return t
} }

View file

@ -45,7 +45,13 @@ pub fn sleep(dur Duration) {
} }
// new_time returns a time struct with the calculated Unix time. // new_time returns a time struct with the calculated Unix time.
@[deprecated: 'use `new()` instead']
@[deprecated_after: '2024-05-31']
pub fn new_time(t Time) Time { pub fn new_time(t Time) Time {
return time_with_unix(t)
}
fn time_with_unix(t Time) Time {
if t.unix != 0 { if t.unix != 0 {
return t return t
} }

View file

@ -36,6 +36,7 @@ pub const days_before = [
// Time contains various time units for a point in time. // Time contains various time units for a point in time.
pub struct Time { pub struct Time {
unix i64
pub: pub:
year int year int
month int month int
@ -44,7 +45,6 @@ pub:
minute int minute int
second int second int
nanosecond int nanosecond int
unix i64
is_local bool // used to make time.now().local().local() == time.now().local() is_local bool // used to make time.now().local().local() == time.now().local()
// //
microsecond int @[deprecated: 'use t.nanosecond / 1000 instead'; deprecated_after: '2023-08-05'] microsecond int @[deprecated: 'use t.nanosecond / 1000 instead'; deprecated_after: '2023-08-05']
@ -87,7 +87,12 @@ pub enum FormatDelimiter {
} }
pub fn Time.new(t Time) Time { pub fn Time.new(t Time) Time {
return new_time(t) return time_with_unix(t)
}
// new returns a time struct with the calculated Unix time.
pub fn new(t Time) Time {
return time_with_unix(t)
} }
// smonth returns the month name abbreviation. // smonth returns the month name abbreviation.
@ -99,29 +104,57 @@ pub fn (t Time) smonth() string {
return time.months_string[i * 3..(i + 1) * 3] return time.months_string[i * 3..(i + 1) * 3]
} }
// unix_time returns the UNIX time with second resolution. // unix returns the UNIX time with second resolution.
@[inline] @[inline]
pub fn (t Time) unix() i64 {
return time_with_unix(t).unix
}
// unix_milli returns the UNIX time with millisecond resolution.
@[inline]
pub fn (t Time) unix_milli() i64 {
return t.unix() * 1_000 + (i64(t.nanosecond) / 1_000_000)
}
// unix_micro returns the UNIX time with microsecond resolution.
@[inline]
pub fn (t Time) unix_micro() i64 {
return t.unix() * 1_000_000 + (i64(t.nanosecond) / 1_000)
}
// unix_nano returns the UNIX time with nanosecond resolution.
@[inline]
pub fn (t Time) unix_nano() i64 {
// TODO: use i128 here, when V supports it, since the following expression overflows for years like 3001:
return t.unix() * 1_000_000_000 + i64(t.nanosecond)
}
// unix_time returns the UNIX time with second resolution.
@[deprecated: 'use `t.unix()` instead']
@[deprecated_after: '2024-05-31']
pub fn (t Time) unix_time() i64 { pub fn (t Time) unix_time() i64 {
return t.unix return t.unix()
} }
// unix_time_milli returns the UNIX time with millisecond resolution. // unix_time_milli returns the UNIX time with millisecond resolution.
@[inline] @[deprecated: 'use `t.unix_milli()` instead']
@[deprecated_after: '2024-05-31']
pub fn (t Time) unix_time_milli() i64 { pub fn (t Time) unix_time_milli() i64 {
return t.unix * 1_000 + (i64(t.nanosecond) / 1_000_000) return t.unix_milli()
} }
// unix_time_micro returns the UNIX time with microsecond resolution. // unix_time_micro returns the UNIX time with microsecond resolution.
@[inline] @[deprecated: 'use `t.unix_micro()` instead']
@[deprecated_after: '2024-05-31']
pub fn (t Time) unix_time_micro() i64 { pub fn (t Time) unix_time_micro() i64 {
return t.unix * 1_000_000 + (i64(t.nanosecond) / 1_000) return t.unix_micro()
} }
// unix_time_nano returns the UNIX time with nanosecond resolution. // unix_time_nano returns the UNIX time with nanosecond resolution.
@[inline] @[deprecated: 'use `t.unix_nano()` instead']
@[deprecated_after: '2024-05-31']
pub fn (t Time) unix_time_nano() i64 { pub fn (t Time) unix_time_nano() i64 {
// TODO: use i128 here, when V supports it, since the following expression overflows for years like 3001: return t.unix_nano()
return t.unix * 1_000_000_000 + i64(t.nanosecond)
} }
// add returns a new time with the given duration added. // add returns a new time with the given duration added.
@ -131,7 +164,7 @@ pub fn (t Time) add(duration_in_nanosecond Duration) Time {
// ... so instead, handle the addition manually in parts ¯\_(ツ)_/¯ // ... so instead, handle the addition manually in parts ¯\_(ツ)_/¯
mut increased_time_nanosecond := i64(t.nanosecond) + duration_in_nanosecond.nanoseconds() mut increased_time_nanosecond := i64(t.nanosecond) + duration_in_nanosecond.nanoseconds()
// increased_time_second // increased_time_second
mut increased_time_second := t.unix + (increased_time_nanosecond / second) mut increased_time_second := t.unix() + (increased_time_nanosecond / second)
increased_time_nanosecond = increased_time_nanosecond % second increased_time_nanosecond = increased_time_nanosecond % second
if increased_time_nanosecond < 0 { if increased_time_nanosecond < 0 {
increased_time_second-- increased_time_second--
@ -143,12 +176,12 @@ pub fn (t Time) add(duration_in_nanosecond Duration) Time {
// add_seconds returns a new time struct with an added number of seconds. // add_seconds returns a new time struct with an added number of seconds.
pub fn (t Time) add_seconds(seconds int) Time { pub fn (t Time) add_seconds(seconds int) Time {
return t.add(seconds * second) return time_with_unix(t).add(seconds * second)
} }
// add_days returns a new time struct with an added number of days. // add_days returns a new time struct with an added number of days.
pub fn (t Time) add_days(days int) Time { pub fn (t Time) add_days(days int) Time {
return t.add(days * 24 * hour) return time_with_unix(t).add(days * 24 * hour)
} }
// since returns the time duration elapsed since a given time. // since returns the time duration elapsed since a given time.
@ -173,7 +206,7 @@ pub fn since(t Time) Duration {
// ``` // ```
pub fn (t Time) relative() string { pub fn (t Time) relative() string {
znow := now() znow := now()
mut secs := znow.unix - t.unix mut secs := znow.unix - t.unix()
mut prefix := '' mut prefix := ''
mut suffix := '' mut suffix := ''
if secs < 0 { if secs < 0 {
@ -235,7 +268,7 @@ pub fn (t Time) relative() string {
// ``` // ```
pub fn (t Time) relative_short() string { pub fn (t Time) relative_short() string {
znow := now() znow := now()
mut secs := znow.unix - t.unix mut secs := znow.unix - t.unix()
mut prefix := '' mut prefix := ''
mut suffix := '' mut suffix := ''
if secs < 0 { if secs < 0 {

View file

@ -7,12 +7,11 @@ const time_to_test = time.Time{
hour: 21 hour: 21
minute: 23 minute: 23
second: 42 second: 42
unix: 332198622
} }
fn test_now_format() { fn test_now_format() {
t := time.now() t := time.now()
u := t.unix u := t.unix()
assert t.format() == time.unix(int(u)).format() assert t.format() == time.unix(int(u)).format()
} }

View file

@ -36,7 +36,8 @@ pub fn (t Time) local() Time {
return t return t
} }
loc_tm := C.tm{} loc_tm := C.tm{}
C.localtime_r(voidptr(&t.unix), &loc_tm) t_ := t.unix()
C.localtime_r(voidptr(&t_), &loc_tm)
return convert_ctime(loc_tm, t.nanosecond) return convert_ctime(loc_tm, t.nanosecond)
} }

View file

@ -1,7 +1,7 @@
import time import time
import math import math
const local_time_to_test = time.Time{ const local_time_to_test = time.new(
year: 1980 year: 1980
month: 7 month: 7
day: 11 day: 11
@ -9,11 +9,10 @@ const local_time_to_test = time.Time{
minute: 23 minute: 23
second: 42 second: 42
nanosecond: 123456789 nanosecond: 123456789
unix: 332198622
is_local: true is_local: true
} )
const utc_time_to_test = time.Time{ const utc_time_to_test = time.new(
year: 1980 year: 1980
month: 7 month: 7
day: 11 day: 11
@ -21,9 +20,8 @@ const utc_time_to_test = time.Time{
minute: 23 minute: 23
second: 42 second: 42
nanosecond: 123456789 nanosecond: 123456789
unix: 332198622
is_local: false is_local: false
} )
fn test_is_leap_year() { fn test_is_leap_year() {
// 1996 % 4 = 0 and 1996 % 100 > 0 // 1996 % 4 = 0 and 1996 % 100 > 0
@ -92,6 +90,8 @@ fn test_unix() {
assert t6.hour == 6 assert t6.hour == 6
assert t6.minute == 9 assert t6.minute == 9
assert t6.second == 29 assert t6.second == 29
assert local_time_to_test.unix() == 332198622
assert utc_time_to_test.unix() == 332198622
} }
fn test_format_rfc3339() { fn test_format_rfc3339() {
@ -168,7 +168,6 @@ fn test_smonth() {
hour: 0 hour: 0
minute: 0 minute: 0
second: 0 second: 0
unix: 0
} }
assert t.smonth() == name assert t.smonth() == name
} }
@ -185,7 +184,6 @@ fn test_day_of_week() {
hour: 0 hour: 0
minute: 0 minute: 0
second: 0 second: 0
unix: 0
} }
assert day_of_week == t.day_of_week() assert day_of_week == t.day_of_week()
} }
@ -238,14 +236,14 @@ fn test_add() {
// dump(t2.debug()) // dump(t2.debug())
assert t2.second == t1.second + d_seconds assert t2.second == t1.second + d_seconds
assert t2.nanosecond == t1.nanosecond + d_nanoseconds assert t2.nanosecond == t1.nanosecond + d_nanoseconds
assert t2.unix == t1.unix + d_seconds assert t2.unix() == t1.unix() + d_seconds
assert t2.is_local == t1.is_local assert t2.is_local == t1.is_local
// //
t3 := local_time_to_test.add(-duration) t3 := local_time_to_test.add(-duration)
// dump(t3.debug()) // dump(t3.debug())
assert t3.second == t1.second - d_seconds assert t3.second == t1.second - d_seconds
assert t3.nanosecond == t1.nanosecond - d_nanoseconds assert t3.nanosecond == t1.nanosecond - d_nanoseconds
assert t3.unix == t1.unix - d_seconds assert t3.unix() == t1.unix() - d_seconds
assert t3.is_local == t1.is_local assert t3.is_local == t1.is_local
// //
t4 := local_time_to_test.as_local() t4 := local_time_to_test.as_local()
@ -253,13 +251,26 @@ fn test_add() {
t5 := t4.add(duration) t5 := t4.add(duration)
// dump(t5.debug()) // dump(t5.debug())
assert t5.is_local == t4.is_local assert t5.is_local == t4.is_local
t := time.Time{
year: 2024
month: 4
day: 3
}
t_5am := t.add(time.hour * 5)
assert t_5am.hour == 5
next_day := t_5am.add_days(1)
assert next_day.day == 4 && next_day.day == t_5am.day + 1
assert next_day.year == t_5am.year && next_day.month == t.month
assert next_day.month == t_5am.month && next_day.month == t.month
assert next_day.hour == t_5am.hour && next_day.month == t.month
} }
fn test_add_days() { fn test_add_days() {
num_of_days := 3 num_of_days := 3
t := local_time_to_test.add_days(num_of_days) t := local_time_to_test.add_days(num_of_days)
assert t.day == local_time_to_test.day + num_of_days assert t.day == local_time_to_test.day + num_of_days
assert t.unix == local_time_to_test.unix + 86400 * num_of_days assert t.unix() == local_time_to_test.unix() + 86400 * num_of_days
} }
fn test_str() { fn test_str() {
@ -304,14 +315,14 @@ fn test_unix_time() {
t2 := time.utc() t2 := time.utc()
eprintln(' t1: ${t1}') eprintln(' t1: ${t1}')
eprintln(' t2: ${t2}') eprintln(' t2: ${t2}')
ut1 := t1.unix_time() ut1 := t1.unix()
ut2 := t2.unix_time() ut2 := t2.unix()
eprintln(' ut1: ${ut1}') eprintln(' ut1: ${ut1}')
eprintln(' ut2: ${ut2}') eprintln(' ut2: ${ut2}')
assert ut2 - ut1 < 2 assert ut2 - ut1 < 2
// //
utm1 := t1.unix_time_milli() utm1 := t1.unix_milli()
utm2 := t2.unix_time_milli() utm2 := t2.unix_milli()
eprintln('utm1: ${utm1}') eprintln('utm1: ${utm1}')
eprintln('utm2: ${utm2}') eprintln('utm2: ${utm2}')
assert (utm1 - ut1 * 1000) < 1000 assert (utm1 - ut1 * 1000) < 1000
@ -370,7 +381,7 @@ fn test_strftime() {
fn test_add_seconds_to_time() { fn test_add_seconds_to_time() {
now_tm := time.now() now_tm := time.now()
future_tm := now_tm.add_seconds(60) future_tm := now_tm.add_seconds(60)
assert now_tm.unix < future_tm.unix assert now_tm.unix() < future_tm.unix()
} }
fn test_plus_equals_duration() { fn test_plus_equals_duration() {
@ -396,6 +407,6 @@ fn test_tm_gmtoff() {
C.time(&rawtime) // C.tm{} C.time(&rawtime) // C.tm{}
info := C.localtime(&rawtime) info := C.localtime(&rawtime)
assert info.tm_gmtoff == time.now().unix - time.utc().unix assert info.tm_gmtoff == time.now().unix() - time.utc().unix()
} }
} }

View file

@ -120,7 +120,7 @@ pub fn (t Time) local() Time {
minute: st_local.minute minute: st_local.minute
second: st_local.second // These are the same second: st_local.second // These are the same
nanosecond: int(st_local.millisecond) * 1_000_000 nanosecond: int(st_local.millisecond) * 1_000_000
unix: st_local.unix_time() unix: st_local.unix()
} }
return t_local return t_local
} }
@ -143,7 +143,7 @@ fn win_now() Time {
minute: st_local.minute minute: st_local.minute
second: st_local.second second: st_local.second
nanosecond: int(st_local.millisecond) * 1_000_000 nanosecond: int(st_local.millisecond) * 1_000_000
unix: st_local.unix_time() unix: st_local.unix()
is_local: true is_local: true
} }
return t return t
@ -165,14 +165,20 @@ fn win_utc() Time {
minute: st_utc.minute minute: st_utc.minute
second: st_utc.second second: st_utc.second
nanosecond: int(st_utc.millisecond) * 1_000_000 nanosecond: int(st_utc.millisecond) * 1_000_000
unix: st_utc.unix_time() unix: st_utc.unix()
is_local: false is_local: false
} }
return t return t
} }
// unix_time returns Unix time. // unix_time returns Unix time.
@[deprecated: 'use `st.unix()` instead']
fn (st SystemTime) unix_time() i64 { fn (st SystemTime) unix_time() i64 {
return st.unix()
}
// unix returns Unix time.
fn (st SystemTime) unix() i64 {
tt := C.tm{ tt := C.tm{
tm_sec: st.second tm_sec: st.second
tm_min: st.minute tm_min: st.minute

View file

@ -1625,8 +1625,14 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
is_used_outside := sym.mod != c.mod is_used_outside := sym.mod != c.mod
if is_used_outside && !field.is_pub && sym.language != .c { if is_used_outside && !field.is_pub && sym.language != .c {
unwrapped_sym := c.table.sym(c.unwrap_generic(typ)) unwrapped_sym := c.table.sym(c.unwrap_generic(typ))
if unwrapped_sym.kind == .struct_ && unwrapped_sym.name == 'time.Time' {
c.add_error_detail('this will become an error after 2024-05-31')
c.warn('field `${unwrapped_sym.name}.${field_name}` is not public, use `${node.expr}.unix()` instead',
node.pos)
} else {
c.error('field `${unwrapped_sym.name}.${field_name}` is not public', node.pos) c.error('field `${unwrapped_sym.name}.${field_name}` is not public', node.pos)
} }
}
field_sym := c.table.sym(field.typ) field_sym := c.table.sym(field.typ)
if field.is_deprecated && is_used_outside { if field.is_deprecated && is_used_outside {
c.deprecate('field', field_name, field.attrs, node.pos) c.deprecate('field', field_name, field.attrs, node.pos)

View file

@ -3,4 +3,4 @@ vlib/v/checker/tests/import_duplicate_err.vv:2:8: error: `time` was already impo
2 | import time 2 | import time
| ~~~~ | ~~~~
3 | fn main() { 3 | fn main() {
4 | println(time.now().unix_time()) 4 | println(time.now().unix())

View file

@ -1,5 +1,5 @@
import time import time
import time import time
fn main() { fn main() {
println(time.now().unix_time()) println(time.now().unix())
} }

View file

@ -2,4 +2,4 @@ vlib/v/checker/tests/import_multiple_modules_err.vv:1:13: error: cannot import m
1 | import time math 1 | import time math
| ~~~~ | ~~~~
2 | fn main() { 2 | fn main() {
3 | println(time.now().unix_time()) 3 | println(time.now().unix())

View file

@ -1,4 +1,4 @@
import time math import time math
fn main() { fn main() {
println(time.now().unix_time()) println(time.now().unix())
} }

View file

@ -153,7 +153,7 @@ fn (mut runner TeamcityTestRunner) fn_error(line_nr int, file string, mod string
} }
fn (mut runner TeamcityTestRunner) test_duration() i64 { fn (mut runner TeamcityTestRunner) test_duration() i64 {
return time.now().unix_time_milli() - runner.start_time.unix_time_milli() return time.now().unix_milli() - runner.start_time.unix_milli()
} }
// print_service prepare and prints a Teamcity service message. // print_service prepare and prints a Teamcity service message.

View file

@ -1,4 +1,4 @@
import time import time
time.now().unix_time() > 160000 time.now().unix() > 160000
===output=== ===output===
true true

View file

@ -3,7 +3,7 @@ import time.misc as tmisc
// using a manual temporary intermediate variable should always work: // using a manual temporary intermediate variable should always work:
fn test_call_fn_that_requires_reference_with_function_that_returns_a_struct_manual() { fn test_call_fn_that_requires_reference_with_function_that_returns_a_struct_manual() {
t1 := tmisc.random() t1 := tmisc.random()
t2 := t1.unix_time() t2 := t1.unix()
println('res: ${t2}') println('res: ${t2}')
assert true assert true
} }
@ -12,7 +12,7 @@ fn test_call_fn_that_requires_reference_with_function_that_returns_a_struct_manu
// TODO: Fix this. // TODO: Fix this.
// v should produce temporary intermediate variables in chained calls: // v should produce temporary intermediate variables in chained calls:
fn test_call_fn_that_requires_reference_with_function_that_returns_a_struct_chained() { fn test_call_fn_that_requires_reference_with_function_that_returns_a_struct_chained() {
res := (tmisc.random().unix_time()) res := (tmisc.random().unix())
println('res: $res') println('res: $res')
assert true assert true
} }

View file

@ -22,7 +22,7 @@ fn test_import() {
assert math.pi == math.pi assert math.pi == math.pi
assert sha512.size == sha512.size assert sha512.size == sha512.size
assert sum('module'.bytes()).hex() == sum('module'.bytes()).hex() assert sum('module'.bytes()).hex() == sum('module'.bytes()).hex()
assert utc().unix_time() == utc().unix_time() assert utc().unix() == utc().unix()
} }
fn test_imports_array_as_fn_arg() { fn test_imports_array_as_fn_arg() {

View file

@ -131,8 +131,8 @@ fn (am AssetManager) get_cache_key(asset_type string) string {
mut latest_modified := i64(0) mut latest_modified := i64(0)
for asset in am.get_assets(asset_type) { for asset in am.get_assets(asset_type) {
files_salt += asset.file_path files_salt += asset.file_path
if asset.last_modified.unix > latest_modified { if asset.last_modified.unix() > latest_modified {
latest_modified = asset.last_modified.unix latest_modified = asset.last_modified.unix()
} }
} }
hash := md5.sum(files_salt.bytes()).hex() hash := md5.sum(files_salt.bytes()).hex()

View file

@ -75,8 +75,8 @@ pub fn set_token(mut ctx vweb.Context, config &CsrfConfig) string {
expire_time := time.now().add_seconds(config.max_age) expire_time := time.now().add_seconds(config.max_age)
session_id := ctx.get_cookie(config.session_cookie) or { '' } session_id := ctx.get_cookie(config.session_cookie) or { '' }
token := generate_token(expire_time.unix_time(), session_id, config.nonce_length) token := generate_token(expire_time.unix(), session_id, config.nonce_length)
cookie := generate_cookie(expire_time.unix_time(), token, config.secret) cookie := generate_cookie(expire_time.unix(), token, config.secret)
// the hmac key is set as a cookie and later validated with `app.token` that must // the hmac key is set as a cookie and later validated with `app.token` that must
// be in an html form // be in an html form
@ -126,7 +126,7 @@ pub fn protect(mut ctx vweb.Context, config &CsrfConfig) bool {
// check the timestamp from the csrftoken against the current time // check the timestamp from the csrftoken against the current time
// if an attacker would change the timestamp on the cookie, the token or both the // if an attacker would change the timestamp on the cookie, the token or both the
// hmac would also change. // hmac would also change.
now := time.now().unix_time() now := time.now().unix()
expire_timestamp := data[0].i64() expire_timestamp := data[0].i64()
if expire_timestamp < now { if expire_timestamp < now {
// token has expired // token has expired

View file

@ -65,7 +65,7 @@ fn test_types() {
assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.hour == fixed_time.hour assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.hour == fixed_time.hour
assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.minute == fixed_time.minute assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.minute == fixed_time.minute
assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.second == fixed_time.second assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.second == fixed_time.second
assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.unix == fixed_time.unix assert json.decode[StructType[time.Time]]('{"val": "2022-03-11T13:54:25.000Z"}')!.val.unix() == fixed_time.unix()
} }
fn test_option_types() { fn test_option_types() {

View file

@ -91,7 +91,7 @@ fn test_parse_user() {
fn test_encode_decode_time() { fn test_encode_decode_time() {
user := User2{ user := User2{
age: 25 age: 25
reg_date: time.new_time(year: 2020, month: 12, day: 22, hour: 7, minute: 23) reg_date: time.new(year: 2020, month: 12, day: 22, hour: 7, minute: 23)
} }
s := json.encode(user) s := json.encode(user)

View file

@ -69,14 +69,14 @@ struct SomeGame {
//! BUGFIX - .from_json(res) //! BUGFIX - .from_json(res)
fn test_encode_decode_sumtype() { fn test_encode_decode_sumtype() {
enc := '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},1,"Stool",{"_type":"Time","value":${t.unix_time()}}]}' enc := '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},1,"Stool",{"_type":"Time","value":${t.unix()}}]}'
dec := json.decode[SomeGame](enc)! dec := json.decode[SomeGame](enc)!
assert game.title == dec.title assert game.title == dec.title
assert game.player == dec.player assert game.player == dec.player
assert (game.other[2] as Animal) == (dec.other[2] as Animal) assert (game.other[2] as Animal) == (dec.other[2] as Animal)
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time() assert (game.other[4] as time.Time).unix() == (dec.other[4] as time.Time).unix()
} }
struct User2 { struct User2 {
@ -116,7 +116,7 @@ fn test_parse_user() {
fn test_encode_decode_time() { fn test_encode_decode_time() {
user := User2{ user := User2{
age: 25 age: 25
reg_date: time.new_time(year: 2020, month: 12, day: 22, hour: 7, minute: 23) reg_date: time.new(year: 2020, month: 12, day: 22, hour: 7, minute: 23)
} }
s := json.encode(user) s := json.encode(user)
assert s.contains('"reg_date":1608621780') assert s.contains('"reg_date":1608621780')

View file

@ -1119,5 +1119,5 @@ fn (mut tm DynamicTemplateManager) handle_dtm_clock() {
// This function is designed for handling timezone adjustments by converting the machine's local time at micro format to a universal micro format. // This function is designed for handling timezone adjustments by converting the machine's local time at micro format to a universal micro format.
// //
fn get_current_unix_micro_timestamp() i64 { fn get_current_unix_micro_timestamp() i64 {
return time.now().unix_time_micro() return time.now().unix_micro()
} }

View file

@ -93,8 +93,8 @@ pub fn set_token(mut ctx vweb.Context, config &CsrfConfig) string {
expire_time := time.now().add_seconds(config.max_age) expire_time := time.now().add_seconds(config.max_age)
session_id := ctx.get_cookie(config.session_cookie) or { '' } session_id := ctx.get_cookie(config.session_cookie) or { '' }
token := generate_token(expire_time.unix_time(), session_id, config.nonce_length) token := generate_token(expire_time.unix(), session_id, config.nonce_length)
cookie := generate_cookie(expire_time.unix_time(), token, config.secret) cookie := generate_cookie(expire_time.unix(), token, config.secret)
// the hmac key is set as a cookie and later validated with `app.token` that must // the hmac key is set as a cookie and later validated with `app.token` that must
// be in an html form // be in an html form
@ -145,7 +145,7 @@ pub fn protect(mut ctx vweb.Context, config &CsrfConfig) bool {
// check the timestamp from the csrftoken against the current time // check the timestamp from the csrftoken against the current time
// if an attacker would change the timestamp on the cookie, the token or both the // if an attacker would change the timestamp on the cookie, the token or both the
// hmac would also change. // hmac would also change.
now := time.now().unix_time() now := time.now().unix()
expire_timestamp := data[0].i64() expire_timestamp := data[0].i64()
if expire_timestamp < now { if expire_timestamp < now {
// token has expired // token has expired