time: turn Time.unix to i64, so it can represent times before 1970-01-01, fix time operators, add more tests (#11050)
parent
1bf6d04e37
commit
efa8dcf4d2
|
@ -38,7 +38,7 @@ pub mut:
|
|||
state State // current state of connection
|
||||
logger &log.Log // logger used to log messages
|
||||
resource_name string // name of current resource
|
||||
last_pong_ut u64 // last time in unix time we got a pong message
|
||||
last_pong_ut i64 // last time in unix time we got a pong message
|
||||
}
|
||||
|
||||
// Flag represents different types of headers in websocket handshake
|
||||
|
|
|
@ -747,6 +747,6 @@ fn test_utime() {
|
|||
f.write_string(hello) or { panic(err) }
|
||||
atime := time.now().add_days(2).unix_time()
|
||||
mtime := time.now().add_days(4).unix_time()
|
||||
os.utime(filename, atime, mtime) or { panic(err) }
|
||||
os.utime(filename, int(atime), int(mtime)) or { panic(err) }
|
||||
assert os.file_last_mod_unix(filename) == mtime
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ const (
|
|||
// users or business transactions.
|
||||
// (https://news.ycombinator.com/item?id=14526173)
|
||||
pub fn ulid() string {
|
||||
return ulid_at_millisecond(time.utc().unix_time_milli())
|
||||
return ulid_at_millisecond(u64(time.utc().unix_time_milli()))
|
||||
}
|
||||
|
||||
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`.
|
||||
|
|
|
@ -37,7 +37,7 @@ fn test_ulids_max_start_character_is_ok() {
|
|||
}
|
||||
|
||||
fn test_ulids_generated_in_the_same_millisecond_have_the_same_prefix() {
|
||||
t := time.utc().unix_time_milli()
|
||||
t := u64(time.utc().unix_time_milli())
|
||||
mut ulid1 := ''
|
||||
mut ulid2 := ''
|
||||
mut ulid3 := ''
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
module time
|
||||
|
||||
// days_from_civil - return the number of days since the
|
||||
// Unix epoch 1970-01-01. A detailed description of the algorithm here
|
||||
// is in: http://howardhinnant.github.io/date_algorithms.html
|
||||
// Note that it will return negative values for days before 1970-01-01.
|
||||
pub fn days_from_civil(oy int, m int, d int) int {
|
||||
y := if m <= 2 { oy - 1 } else { oy }
|
||||
era := y / 400
|
||||
yoe := y - era * 400 // [0, 399]
|
||||
doy := (153 * (m + (if m > 2 { -3 } else { 9 })) + 2) / 5 + d - 1 // [0, 365]
|
||||
doe := yoe * 365 + yoe / 4 - yoe / 100 + doy // [0, 146096]
|
||||
return era * 146097 + doe - 719468
|
||||
}
|
||||
|
||||
// portable_timegm does the same as C._mkgmtime, but unlike it,
|
||||
// can work with dates before the Unix epoch of 1970-01-01 .
|
||||
pub fn portable_timegm(t &C.tm) i64 {
|
||||
mut year := t.tm_year + 1900
|
||||
mut month := t.tm_mon // 0-11
|
||||
if month > 11 {
|
||||
year += month / 12
|
||||
month %= 12
|
||||
} else if month < 0 {
|
||||
years_diff := (11 - month) / 12
|
||||
year -= years_diff
|
||||
month += 12 * years_diff
|
||||
}
|
||||
days_since_1970 := i64(days_from_civil(year, month + 1, t.tm_mday))
|
||||
return 60 * (60 * (24 * days_since_1970 + t.tm_hour) + t.tm_min) + t.tm_sec
|
||||
}
|
|
@ -9,5 +9,5 @@ const (
|
|||
|
||||
// random returns a random time struct in *the past*.
|
||||
pub fn random() time.Time {
|
||||
return time.unix(int(rand.u64n(misc.start_time_unix)))
|
||||
return time.unix(int(rand.i64n(misc.start_time_unix)))
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ pub fn (t1 Time) < (t2 Time) bool {
|
|||
// Time subtract using operator overloading.
|
||||
[inline]
|
||||
pub fn (lhs Time) - (rhs Time) Duration {
|
||||
lhs_micro := lhs.unix * 1000 * 1000 + u64(lhs.microsecond)
|
||||
rhs_micro := rhs.unix * 1000 * 1000 + u64(rhs.microsecond)
|
||||
return (i64(lhs_micro) - i64(rhs_micro)) * microsecond
|
||||
lhs_micro := lhs.unix * 1_000_000 + lhs.microsecond
|
||||
rhs_micro := rhs.unix * 1_000_000 + rhs.microsecond
|
||||
return (lhs_micro - rhs_micro) * microsecond
|
||||
}
|
||||
|
|
|
@ -131,9 +131,9 @@ pub fn parse_iso8601(s string) ?Time {
|
|||
}
|
||||
mut unix_time := t.unix
|
||||
if unix_offset < 0 {
|
||||
unix_time -= u64(-unix_offset)
|
||||
unix_time -= (-unix_offset)
|
||||
} else if unix_offset > 0 {
|
||||
unix_time += u64(unix_offset)
|
||||
unix_time += unix_offset
|
||||
}
|
||||
t = unix2(i64(unix_time), t.microsecond)
|
||||
return t
|
||||
|
|
|
@ -50,7 +50,7 @@ pub:
|
|||
minute int
|
||||
second int
|
||||
microsecond int
|
||||
unix u64
|
||||
unix i64
|
||||
}
|
||||
|
||||
// FormatDelimiter contains different time formats.
|
||||
|
@ -162,7 +162,7 @@ pub fn new_time(t Time) Time {
|
|||
tm_mon: t.month - 1
|
||||
tm_year: t.year - 1900
|
||||
}
|
||||
utime := u64(make_unix_time(tt))
|
||||
utime := make_unix_time(tt)
|
||||
return Time{
|
||||
...t
|
||||
unix: utime
|
||||
|
@ -171,21 +171,21 @@ pub fn new_time(t Time) Time {
|
|||
|
||||
// unix_time returns Unix time.
|
||||
[inline]
|
||||
pub fn (t Time) unix_time() int {
|
||||
return int(t.unix)
|
||||
pub fn (t Time) unix_time() i64 {
|
||||
return t.unix
|
||||
}
|
||||
|
||||
// unix_time_milli returns Unix time with millisecond resolution.
|
||||
[inline]
|
||||
pub fn (t Time) unix_time_milli() u64 {
|
||||
return t.unix * 1000 + u64(t.microsecond / 1000)
|
||||
pub fn (t Time) unix_time_milli() i64 {
|
||||
return t.unix * 1000 + (t.microsecond / 1000)
|
||||
}
|
||||
|
||||
// add returns a new time that duration is added
|
||||
pub fn (t Time) add(d Duration) Time {
|
||||
microseconds := i64(t.unix) * 1000 * 1000 + t.microsecond + d.microseconds()
|
||||
unix := microseconds / (1000 * 1000)
|
||||
micro := microseconds % (1000 * 1000)
|
||||
microseconds := i64(t.unix) * 1_000_000 + t.microsecond + d.microseconds()
|
||||
unix := microseconds / 1_000_000
|
||||
micro := microseconds % 1_000_000
|
||||
return unix2(unix, int(micro))
|
||||
}
|
||||
|
||||
|
@ -358,6 +358,11 @@ pub fn (t Time) str() string {
|
|||
return t.format_ss()
|
||||
}
|
||||
|
||||
// str returns time in the same format as `parse` expects ("YYYY-MM-DD HH:MM:SS").
|
||||
pub fn (t Time) debug() string {
|
||||
return 'Time{ year: ${t.year:04} month: ${t.month:02} day: ${t.day:02} hour: ${t.hour:02} minute: ${t.minute:02} second: ${t.second:02} microsecond: ${t.microsecond:06} unix: ${t.unix:07} }'
|
||||
}
|
||||
|
||||
// convert_ctime converts a C time to V time.
|
||||
fn convert_ctime(t C.tm, microsecond int) Time {
|
||||
return Time{
|
||||
|
@ -368,7 +373,7 @@ fn convert_ctime(t C.tm, microsecond int) Time {
|
|||
minute: t.tm_min
|
||||
second: t.tm_sec
|
||||
microsecond: time.microsecond
|
||||
unix: u64(make_unix_time(t))
|
||||
unix: make_unix_time(t)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import time
|
||||
|
||||
fn test_add_to_day_in_the_previous_century() ? {
|
||||
a := time.parse_iso8601('1900-01-01') ?
|
||||
aa := a.add_days(180)
|
||||
dump(a.debug())
|
||||
dump(aa.debug())
|
||||
assert aa.ymmdd() == '1900-06-29'
|
||||
}
|
||||
|
||||
fn test_add_to_day_in_the_past() ? {
|
||||
a := time.parse_iso8601('1990-03-01') ?
|
||||
aa := a.add_days(180)
|
||||
assert aa.ymmdd() == '1990-08-27'
|
||||
}
|
||||
|
||||
fn test_add_to_day_in_the_recent_past() ? {
|
||||
a := time.parse_iso8601('2021-03-01') ?
|
||||
aa := a.add_days(180)
|
||||
assert aa.ymmdd() == '2021-08-28'
|
||||
}
|
||||
|
||||
fn test_add_to_day_in_the_future_1() ? {
|
||||
a := time.parse_iso8601('3000-11-01') ?
|
||||
aa := a.add_days(180)
|
||||
assert aa.ymmdd() == '3001-04-30'
|
||||
}
|
||||
|
||||
fn test_add_to_day_in_the_future_2() ? {
|
||||
a := time.parse_iso8601('3000-12-30') ?
|
||||
aa := a.add_days(180)
|
||||
assert aa.ymmdd() == '3001-06-28'
|
||||
}
|
|
@ -23,8 +23,8 @@ fn C.timegm(&C.tm) C.time_t
|
|||
// fn C.gmtime_r(&tm, &gbuf)
|
||||
fn C.localtime_r(t &time_t, tm &C.tm)
|
||||
|
||||
fn make_unix_time(t C.tm) int {
|
||||
return int(C.timegm(&t))
|
||||
fn make_unix_time(t C.tm) i64 {
|
||||
return i64(C.timegm(&t))
|
||||
}
|
||||
|
||||
// local returns t with the location set to local time.
|
||||
|
|
|
@ -160,18 +160,18 @@ fn test_add() {
|
|||
t2 := time_to_test.add(duration)
|
||||
assert t2.second == t1.second + d_seconds
|
||||
assert t2.microsecond == t1.microsecond + d_microseconds
|
||||
assert t2.unix == t1.unix + u64(d_seconds)
|
||||
assert t2.unix == t1.unix + d_seconds
|
||||
t3 := time_to_test.add(-duration)
|
||||
assert t3.second == t1.second - d_seconds
|
||||
assert t3.microsecond == t1.microsecond - d_microseconds
|
||||
assert t3.unix == t1.unix - u64(d_seconds)
|
||||
assert t3.unix == t1.unix - d_seconds
|
||||
}
|
||||
|
||||
fn test_add_days() {
|
||||
num_of_days := 3
|
||||
t := time_to_test.add_days(num_of_days)
|
||||
assert t.day == time_to_test.day + num_of_days
|
||||
assert t.unix == time_to_test.unix + 86400 * u64(num_of_days)
|
||||
assert t.unix == time_to_test.unix + 86400 * num_of_days
|
||||
}
|
||||
|
||||
fn test_str() {
|
||||
|
@ -217,8 +217,8 @@ fn test_unix_time() {
|
|||
//
|
||||
utm1 := t1.unix_time_milli()
|
||||
utm2 := t2.unix_time_milli()
|
||||
assert (utm1 - u64(ut1) * 1000) < 1000
|
||||
assert (utm2 - u64(ut2) * 1000) < 1000
|
||||
assert (utm1 - ut1 * 1000) < 1000
|
||||
assert (utm2 - ut2 * 1000) < 1000
|
||||
//
|
||||
// println('utm1: $utm1 | utm2: $utm2')
|
||||
assert utm2 - utm1 > 2
|
||||
|
|
|
@ -52,14 +52,12 @@ struct C.timespec {
|
|||
tv_nsec i64
|
||||
}
|
||||
|
||||
fn C._mkgmtime(&C.tm) C.time_t
|
||||
|
||||
fn C.QueryPerformanceCounter(&u64) C.BOOL
|
||||
|
||||
fn C.QueryPerformanceFrequency(&u64) C.BOOL
|
||||
|
||||
fn make_unix_time(t C.tm) int {
|
||||
return int(C._mkgmtime(&t))
|
||||
fn make_unix_time(t C.tm) i64 {
|
||||
return portable_timegm(&t)
|
||||
}
|
||||
|
||||
fn init_win_time_freq() u64 {
|
||||
|
@ -91,7 +89,7 @@ fn vpc_now() u64 {
|
|||
}
|
||||
|
||||
// local_as_unix_time returns the current local time as unix time
|
||||
fn local_as_unix_time() int {
|
||||
fn local_as_unix_time() i64 {
|
||||
t := C.time(0)
|
||||
tm := C.localtime(&t)
|
||||
return make_unix_time(tm)
|
||||
|
@ -117,7 +115,7 @@ pub fn (t Time) local() Time {
|
|||
minute: st_local.minute
|
||||
second: st_local.second // These are the same
|
||||
microsecond: st_local.millisecond * 1000
|
||||
unix: u64(st_local.unix_time())
|
||||
unix: st_local.unix_time()
|
||||
}
|
||||
return t_local
|
||||
}
|
||||
|
@ -140,7 +138,7 @@ fn win_now() Time {
|
|||
minute: st_local.minute
|
||||
second: st_local.second
|
||||
microsecond: st_local.millisecond * 1000
|
||||
unix: u64(st_local.unix_time())
|
||||
unix: st_local.unix_time()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
@ -161,13 +159,13 @@ fn win_utc() Time {
|
|||
minute: st_utc.minute
|
||||
second: st_utc.second
|
||||
microsecond: st_utc.millisecond * 1000
|
||||
unix: u64(st_utc.unix_time())
|
||||
unix: st_utc.unix_time()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// unix_time returns Unix time.
|
||||
pub fn (st SystemTime) unix_time() int {
|
||||
pub fn (st SystemTime) unix_time() i64 {
|
||||
tt := C.tm{
|
||||
tm_sec: st.second
|
||||
tm_min: st.minute
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn unix(abs int) Time {
|
|||
hour: hr
|
||||
minute: min
|
||||
second: sec
|
||||
unix: u64(abs)
|
||||
unix: abs
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub fn unix2(abs i64, microsecond int) Time {
|
|||
minute: min
|
||||
second: sec
|
||||
microsecond: microsecond
|
||||
unix: u64(abs)
|
||||
unix: abs
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ fn (am AssetManager) combine(asset_type string, to_file bool) string {
|
|||
|
||||
fn (am AssetManager) get_cache_key(asset_type string) string {
|
||||
mut files_salt := ''
|
||||
mut latest_modified := u64(0)
|
||||
mut latest_modified := i64(0)
|
||||
for asset in am.get_assets(asset_type) {
|
||||
files_salt += asset.file_path
|
||||
if asset.last_modified.unix > latest_modified {
|
||||
|
@ -151,7 +151,7 @@ fn (mut am AssetManager) add(asset_type string, file string) bool {
|
|||
asset := Asset{
|
||||
file_path: file
|
||||
last_modified: time.Time{
|
||||
unix: u64(os.file_last_mod_unix(file))
|
||||
unix: os.file_last_mod_unix(file)
|
||||
}
|
||||
}
|
||||
if asset_type == 'css' {
|
||||
|
|
Loading…
Reference in New Issue