diff --git a/vlib/time/chrono.c.v b/vlib/time/chrono.c.v new file mode 100644 index 0000000000..4d6de7d99f --- /dev/null +++ b/vlib/time/chrono.c.v @@ -0,0 +1,18 @@ +module time + +// 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 +} diff --git a/vlib/time/chrono.v b/vlib/time/chrono.v index 209d3dfe6c..58f1ef8c76 100644 --- a/vlib/time/chrono.v +++ b/vlib/time/chrono.v @@ -12,20 +12,3 @@ pub fn days_from_civil(oy int, m int, d int) int { 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 -} diff --git a/vlib/time/parse.v b/vlib/time/parse.c.v similarity index 100% rename from vlib/time/parse.v rename to vlib/time/parse.c.v diff --git a/vlib/time/time.c.v b/vlib/time/time.c.v new file mode 100644 index 0000000000..89d2142752 --- /dev/null +++ b/vlib/time/time.c.v @@ -0,0 +1,121 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module time + +#include + +// C.timeval represents a C time value. +pub struct C.timeval { + tv_sec u64 + tv_usec u64 +} + +fn C.localtime(t &C.time_t) &C.tm + +fn C.time(t &C.time_t) C.time_t + +// now returns current local time. +pub fn now() Time { + $if macos { + return darwin_now() + } + $if windows { + return win_now() + } + $if solaris { + return solaris_now() + } + $if linux || android { + return linux_now() + } + // defaults to most common feature, the microsecond precision is not available + // in this API call + t := C.time(0) + now := C.localtime(&t) + return convert_ctime(*now, 0) +} + +// utc returns the current UTC time. +pub fn utc() Time { + $if macos { + return darwin_utc() + } + $if windows { + return win_utc() + } + $if solaris { + return solaris_utc() + } + $if linux || android { + return linux_utc() + } + // defaults to most common feature, the microsecond precision is not available + // in this API call + t := C.time(0) + _ = C.time(&t) + return unix2(i64(t), 0) +} + +// new_time returns a time struct with calculated Unix time. +pub fn new_time(t Time) Time { + if t.unix != 0 { + return t + } + tt := C.tm{ + tm_sec: t.second + tm_min: t.minute + tm_hour: t.hour + tm_mday: t.day + tm_mon: t.month - 1 + tm_year: t.year - 1900 + } + utime := make_unix_time(tt) + return Time{ + ...t + unix: utime + } +} + +// ticks returns a number of milliseconds elapsed since system start. +pub fn ticks() i64 { + $if windows { + return C.GetTickCount() + } $else { + ts := C.timeval{} + C.gettimeofday(&ts, 0) + return i64(ts.tv_sec * u64(1000) + (ts.tv_usec / u64(1000))) + } + // t := i64(C.mach_absolute_time()) + // # Nanoseconds elapsedNano = AbsoluteToNanoseconds( *(AbsoluteTime *) &t ); + // # return (double)(* (uint64_t *) &elapsedNano) / 1000000; +} + +/* +// sleep makes the calling thread sleep for a given number of seconds. +[deprecated: 'call time.sleep(n * time.second)'] +pub fn sleep(seconds int) { + wait(seconds * time.second) +} +*/ + +// str returns time in the same format as `parse` expects ("YYYY-MM-DD HH:MM:SS"). +pub fn (t Time) str() string { + // TODO Define common default format for + // `str` and `parse` and use it in both ways + return t.format_ss() +} + +// convert_ctime converts a C time to V time. +fn convert_ctime(t C.tm, microsecond int) Time { + return Time{ + year: t.tm_year + 1900 + month: t.tm_mon + 1 + day: t.tm_mday + hour: t.tm_hour + minute: t.tm_min + second: t.tm_sec + microsecond: microsecond + unix: make_unix_time(t) + } +} diff --git a/vlib/time/time.v b/vlib/time/time.v index dbb012bf89..5ce4fcbac3 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -1,10 +1,5 @@ -// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. module time -#include - pub const ( days_string = 'MonTueWedThuFriSatSun' month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] @@ -88,58 +83,6 @@ pub enum FormatDelimiter { no_delimiter } -// C.timeval represents a C time value. -pub struct C.timeval { - tv_sec u64 - tv_usec u64 -} - -fn C.localtime(t &C.time_t) &C.tm - -fn C.time(t &C.time_t) C.time_t - -// now returns current local time. -pub fn now() Time { - $if macos { - return darwin_now() - } - $if windows { - return win_now() - } - $if solaris { - return solaris_now() - } - $if linux || android { - return linux_now() - } - // defaults to most common feature, the microsecond precision is not available - // in this API call - t := C.time(0) - now := C.localtime(&t) - return convert_ctime(*now, 0) -} - -// utc returns the current UTC time. -pub fn utc() Time { - $if macos { - return darwin_utc() - } - $if windows { - return win_utc() - } - $if solaris { - return solaris_utc() - } - $if linux || android { - return linux_utc() - } - // defaults to most common feature, the microsecond precision is not available - // in this API call - t := C.time(0) - _ = C.time(&t) - return unix2(i64(t), 0) -} - // smonth returns month name. pub fn (t Time) smonth() string { if t.month <= 0 || t.month > 12 { @@ -149,26 +92,6 @@ pub fn (t Time) smonth() string { return time.months_string[i * 3..(i + 1) * 3] } -// new_time returns a time struct with calculated Unix time. -pub fn new_time(t Time) Time { - if t.unix != 0 { - return t - } - tt := C.tm{ - tm_sec: t.second - tm_min: t.minute - tm_hour: t.hour - tm_mday: t.day - tm_mon: t.month - 1 - tm_year: t.year - 1900 - } - utime := make_unix_time(tt) - return Time{ - ...t - unix: utime - } -} - // unix_time returns Unix time. [inline] pub fn (t Time) unix_time() i64 { @@ -314,28 +237,6 @@ pub fn (t Time) long_weekday_str() string { return time.long_days[i] } -// ticks returns a number of milliseconds elapsed since system start. -pub fn ticks() i64 { - $if windows { - return C.GetTickCount() - } $else { - ts := C.timeval{} - C.gettimeofday(&ts, 0) - return i64(ts.tv_sec * u64(1000) + (ts.tv_usec / u64(1000))) - } - // t := i64(C.mach_absolute_time()) - // # Nanoseconds elapsedNano = AbsoluteToNanoseconds( *(AbsoluteTime *) &t ); - // # return (double)(* (uint64_t *) &elapsedNano) / 1000000; -} - -/* -// sleep makes the calling thread sleep for a given number of seconds. -[deprecated: 'call time.sleep(n * time.second)'] -pub fn sleep(seconds int) { - wait(seconds * time.second) -} -*/ - // is_leap_year checks if a given a year is a leap year. pub fn is_leap_year(year int) bool { return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0) @@ -351,32 +252,11 @@ pub fn days_in_month(month int, year int) ?int { return res } -// str returns time in the same format as `parse` expects ("YYYY-MM-DD HH:MM:SS"). -pub fn (t Time) str() string { - // TODO Define common default format for - // `str` and `parse` and use it in both ways - 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{ - year: t.tm_year + 1900 - month: t.tm_mon + 1 - day: t.tm_mday - hour: t.tm_hour - minute: t.tm_min - second: t.tm_sec - microsecond: time.microsecond - unix: make_unix_time(t) - } -} - // A lot of these are taken from the Go library. pub type Duration = i64