diff --git a/examples/game_of_life/life.v b/examples/game_of_life/life.v index 7796a69883..79e79f3ff5 100644 --- a/examples/game_of_life/life.v +++ b/examples/game_of_life/life.v @@ -73,7 +73,7 @@ fn main() { } field = new_field print_field(field) - time.sleep_ms(100) + time.sleep(time.milliseconds(100)) } } diff --git a/examples/news_fetcher.v b/examples/news_fetcher.v index 3cb1a94107..61f1a2f0a0 100644 --- a/examples/news_fetcher.v +++ b/examples/news_fetcher.v @@ -53,6 +53,6 @@ fn main() { go fetcher.fetch() } println(fetcher.ids) - time.sleep(5) + time.sleep(time.seconds(5)) } diff --git a/examples/tetris/tetris.v b/examples/tetris/tetris.v index 6eb728a328..f03cd5606a 100644 --- a/examples/tetris/tetris.v +++ b/examples/tetris/tetris.v @@ -17,7 +17,7 @@ const ( TetroSize = 4 WinWidth = BlockSize * FieldWidth WinHeight = BlockSize * FieldHeight - TimerPeriod = 250 // ms + TimerPeriod = time.milliseconds(250) // 250ms ) const ( @@ -168,7 +168,7 @@ fn (g mut Game) run() { g.move_tetro() g.delete_completed_lines() glfw.post_empty_event() // force window redraw - time.sleep_ms(TimerPeriod) + time.sleep(TimerPeriod) } } diff --git a/time/info.v b/time/info.v new file mode 100644 index 0000000000..dac64dcca9 --- /dev/null +++ b/time/info.v @@ -0,0 +1,17 @@ +// Copyright (c) 2019 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 + +struct Info { +pub: + year int + month int + day int + hour int + minute int + second int + yday int + wday int +} diff --git a/time/time.v b/time/time.v index a544723014..dc02c31893 100644 --- a/time/time.v +++ b/time/time.v @@ -4,337 +4,104 @@ module time -import rand - #include + struct Time { -pub: - year int - month int - day int - hour int - minute int - second int - uni int // TODO it's safe to use "unix" now + sec i64 + nsec i32 + mono i64 } -fn remove_me_when_c_bug_is_fixed() { // TODO -} - -struct C.tm { - tm_year int - tm_mon int - tm_mday int - tm_hour int - tm_min int - tm_sec int -} - -pub fn now() Time { - # time_t t = time(0); - // t := C.time(0) - # struct tm * now = localtime(&t); - res := Time{} - # res.year = now->tm_year + 1900; - # res.month = now->tm_mon + 1; - # res.day = now->tm_mday; - # res.hour = now->tm_hour; - # res.minute = now->tm_min; - # res.second = now->tm_sec; - # res.uni = (int)t; - // # res.ms = now->tm_msec; - return res -} - -// fn now() Time { -// t := C.time(0) -// now := localtime(&t) -// return Time{ -// year: now.tm_year + 1900 -// month : now.tm_mon + 1 -// day : now.tm_mday -// hour : now.tm_hour -// minute : now.tm_min -// second : now.tm_sec -// uni : int(t) -// } -// } -pub fn random() Time { - return Time { - year: rand.next(2) + 201 - month: rand.next(12) + 1 - day: rand.next(30) + 1 - hour: rand.next(24) - minute: rand.next(60) - second: rand.next(60) +fn (a Time) + (b Time) Time { + sec := a.sec + b.sec + nsec := a.nsec + b.nsec + return Time{ + sec: sec + i64(nsec)/i64(1000000000) + nsec: nsec % i32(1000000000) } } -pub fn unix(u string) Time { - // println('unix time($u)') - // # int aa = atoi(u.str); - // #printf("!!!! %d\n", aa); - # int uni = atoi(u.str); - # time_t t = (time_t)uni; - # struct tm * now = localtime(&t); - // println('got tm') - // TODO COPY PASTA - res := Time{} - # res.year = now->tm_year + 1900; - # res.month = now->tm_mon + 1; - # res.day = now->tm_mday; - # res.hour = now->tm_hour; - # res.minute = now->tm_min; - # res.second = now->tm_sec; - # res.uni = uni; - // println('end unix') - return res -} - -pub fn convert_ctime(t tm) 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 +fn (a Time) - (b Time) Time { + sec := a.sec - b.sec - i64(1) + nsec := a.nsec - b.nsec + i32(1000000000) + t := Time{ + sec: sec + i64(nsec)/i64(1000000000) + nsec: nsec % i32(1000000000) } - // uni = uni; -} - -pub fn unixn(uni int) Time { - // println('unix time($u)') - // # int aa = atoi(u.str); - // #printf("!!!! %d\n", aa); - # time_t t = (time_t)uni; - # struct tm * now = localtime(&t); - // println('got tm') - // TODO COPY PASTA - res := Time{} - # res.year = now->tm_year + 1900; - # res.month = now->tm_mon + 1; - # res.day = now->tm_mday; - # res.hour = now->tm_hour; - # res.minute = now->tm_min; - # res.second = now->tm_sec; - # res.uni = uni; - // println('end unix') - return res -} - -fn (t Time) format_ss() string { - return '${t.year}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}:${t.second:02d}' -} - -pub fn (t Time) format() string { - return '${t.year}-${t.month:02d}-${t.day:02d} ${t.hour:02d}:${t.minute:02d}' -} - -const ( - Months = 'JanFebMarAprMayJunJulAugSepOctNovDec' - Days = 'MonTueWedThuFriSatSun' -) - -pub fn (t Time) smonth() string { - i := t.month - 1 - return Months.substr(i * 3, (i + 1) * 3) -} - -// 21:04 -pub fn (t Time) hhmm() string { - return '${t.hour:02d}:${t.minute:02d}' -} - -fn (t Time) hhmm_tmp() string { - return '${t.hour:02d}:${t.minute:02d}' -} - -// 21:04 -pub fn (t Time) hhmm12() string { - mut am := 'am' - mut hour = t.hour - if t.hour > 11 { - am = 'pm' + if a.mono <= i64(0) || b.mono <= i64(0) { + return t } - if t.hour > 12 { - hour = hour - 12 + + mono := a.mono - b.mono + if mono > i64(0) && t.sec >= i64(0) && t.nsec >= i32(0) { + return t } - if t.hour == 0 { - hour = 12 + if mono < i64(0) && t.sec <= i64(0) && t.nsec <= i32(0) { + return t + } + if mono == i64(0) { + return Time{} + } + return Time{ + sec: mono / i64(1000000000) + nsec: i32(mono%i64(1000000000)) } - return '$hour:${t.minute:02d} $am' } -// 21:04:03 -fn (t Time) hhmmss() string { - return '${t.hour:02d}:${t.minute:02d}:${t.second:02d}' +fn (t Time) days() f64 { + return f64(t.sec)/86400.0 } -// 2012-01-05 -fn (t Time) ymmdd() string { - return '${t.year}-${t.month:02d}-${t.day:02d}' +fn (t Time) hours() f64 { + return f64(t.sec)/3600.0 } -// Jul 3 -fn (t Time) md() string { - // jl := t.smonth() - s := '${t.smonth()} $t.day' - return s +fn (t Time) minutes() f64 { + return f64(t.sec)/60.0 } -fn (t Time) clean() string { - nowe := time.now() - // if amtime { - // hm = t.Format("3:04 pm") - // } - // Today - if t.month == nowe.month && t.year == nowe.year && t.day == nowe.day { - return t.hhmm() +fn (t Time) seconds() f64 { + return f64(t.sec) + f64(t.nsec)/1000000000.0 +} + +fn (t Time) milliseconds() f64 { + return 1000.0*f64(t.sec) + f64(t.nsec)/1000000.0 +} + +fn (t Time) microseconds() f64 { + return 1000000.0*f64(t.sec) + f64(t.nsec)/1000.0 +} + +fn (t Time) nanoseconds() f64 { + return 1000000000.0*f64(t.sec) + f64(t.nsec) +} + +fn (t Time) str() string { + if t.sec == i64(0) { + if t.nsec == i32(0) { + return '0s' + } + if t.nsec < i32(1000) && t.nsec > i32(-1000) { + return '${t.nsec}ns' + } + if t.nsec < i32(1000000) && t.nsec > i32(-1000000) { + return '${f64(t.nsec)/1000.0:.1f}µs' + } + if t.nsec < i32(1000000000) && t.nsec > i32(-1000000000) { + return '${f64(t.nsec)/1000000.0:.1f}ms' + } } - // This week - // if time.Since(t) < 24*7*time.Hour { - // return t.Weekday().String()[:3] + " " + hm - // } - // This year - if t.year == nowe.year { - return '${t.smonth()} ${t.day} ${t.hhmm()}' + if t.sec < i64(60) && t.sec > i64(-60) { + return '${f64(t.sec)+f64(t.nsec)/1000000000.0:.1f}s' } - return t.format() - // return fmt.Sprintf("%4d/%02d/%02d", t.Year(), t.Month(), t.Day()) + " " + hm -} - -fn (t Time) clean12() string { - nowe := time.now() - // if amtime { - // hm = t.Format("3:04 pm") - // } - // Today - if t.month == nowe.month && t.year == nowe.year && t.day == nowe.day { - return t.hhmm12() + if t.sec < i64(3600) && t.sec > i64(-3600) { + return '${f64(t.sec)/60.0:.1f}m' } - // This week - // if time.Since(t) < 24*7*time.Hour { - // return t.Weekday().String()[:3] + " " + hm - // } - // This year - if t.year == nowe.year { - return '${t.smonth()} ${t.day} ${t.hhmm12()}' + if t.sec < i64(86400) && t.sec > i64(-86400) { + return '${f64(t.sec)/3600.0:.1f}h' } - return t.format() - // return fmt.Sprintf("%4d/%02d/%02d", t.Year(), t.Month(), t.Day()) + " " + hm -} - -/* -// in ms -fn ticks() double { - # struct timeval tv; - # gettimeofday(&tv, NULL); - # double time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond - // # printf("!!!%f\n", time_in_mill); - // # return (int)time_in_mill; - // # return (int)(time_in_mill - 1521561736529); - # return (long)(time_in_mill - 1523777913000); - return double(0) - // return int64(0) -} -*/ -// `parse` parses time in the following format: "2018-01-27 12:48:34" -pub fn parse(s string) Time { - // println('parse="$s"') - pos := s.index(' ') - if pos <= 0 { - println('bad time format') - return now() + if t.sec < i64(864000) && t.sec > i64(-864000) { + return '${f64(t.sec)/86400.0:.1f}d' } - symd := s.left(pos) - ymd := symd.split('-') - if ymd.len != 3 { - println('bad time format') - return now() - } - shms := s.right(pos) - hms := shms.split(':') - hour := hms[0] - minute := hms[1] - second := hms[2] - // ////////// - return new_time(Time { - year: ymd[0].int() - month: ymd[1].int() - day: ymd[2].int() - hour: hour.int() - minute: minute.int() - second: second.int() - }) -} - -fn new_time(t Time) Time { - return{t | uni: t.calc_unix()} -} - -fn (t &Time) calc_unix() int { - # struct tm lDate; - # lDate.tm_sec = t->second; - # lDate.tm_min = t->minute; - # lDate.tm_hour = t->hour; - # lDate.tm_mday = t->day; - # lDate.tm_mon = t->month-1; - # lDate.tm_year = t->year - 1900; - # time_t kek = mktime(&lDate); - // # t->uni = (int)kek; - # return (int)kek; - return 0 -} - -// TODO add(d time.Duration) -pub fn (t Time) add_seconds(seconds int) Time { - return unixn(t.uni + seconds) -} - -// TODO use time.Duration instead of seconds -fn since(t Time) int { - return 0 -} - -pub fn (t Time) relative() string { - now := time.now() - secs := now.uni - t.uni - if secs <= 30 { - // right now or in the future - // TODO handle time in the future - return 'now' - } - if secs < 60 { - return '1m' - } - if secs < 3600 { - return '${secs/60}m' - } - if secs < 3600 * 24 { - return '${secs/3600}h' - } - if secs < 3600 * 24 * 5 { - return '${secs/3600/24}d' - } - if secs > 3600 * 24 * 10000 { - return '' - } - return t.md() -} - -fn day_of_week(y, m, d int) int { - // TODO please no - # return (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7; - return 0 -} - -pub fn (t Time) day_of_week() int { - return day_of_week(t.year, t.month, t.day) -} - -// weekday_str() returns the current day in string (upto 3 characters) -pub fn (t Time) weekday_str() string { - i := t.day_of_week() - 1 - return Days.substr(i * 3, (i + 1) * 3) + return '${f64(t.sec)/86400.0:.0f}d' } diff --git a/time/time_lin.v b/time/time_lin.v index e3291c26dd..8e365daaef 100644 --- a/time/time_lin.v +++ b/time/time_lin.v @@ -4,16 +4,84 @@ module time -// in ms -pub fn ticks() f64 { - return f64(0) +pub fn now() Time { + # struct timespec t = {0, 0}; + # struct timespec m = {0, 0}; + # clock_gettime(CLOCK_REALTIME, &t); + # clock_gettime(CLOCK_MONOTONIC_RAW, &m); + + res := Time{} + # res.sec = t.tv_sec; + # res.nsec = t.tv_nsec; + # res.mono = 1000000000*m.tv_sec + m.tv_nsec; + return res } -pub fn sleep(seconds int) { - C.sleep(seconds) +pub fn sleep(t Time) { + if t.sec > i64(0) { + C.sleep(t.sec) + } + if t.nsec > i32(0) { + C.usleep((t.nsec+i32(999))/i32(1000)) + } } -pub fn sleep_ms(seconds int) { - C.usleep(seconds * 1000) +fn (t Time) local() Info { + info := Info{} + # struct tm tm; + # localtime_r(&t.sec, &tm); + # info.year = tm.tm_year + 1900; + # info.month = tm.tm_mon + 1; + # info.day = tm.tm_mday; + # info.hour = tm.tm_hour; + # info.minute = tm.tm_min; + # info.second = tm.tm_sec; + # info.yday = tm.tm_yday; + # info.wday = tm.tm_wday; + return info } +fn (t Time) utc() Info { + info := Info{} + # struct tm tm; + # gmtime_r(&t.sec, &tm); + # info.year = tm.tm_year + 1900; + # info.month = tm.tm_mon + 1; + # info.day = tm.tm_mday; + # info.hour = tm.tm_hour; + # info.minute = tm.tm_min; + # info.second = tm.tm_sec; + # info.yday = tm.tm_yday; + # info.wday = tm.tm_wday; + return info +} + +fn (t Time) format(fmt string) string { + res := '' + cfmt := fmt.cstr() + # char buf[1024]; + # struct tm tm; + # localtime_r(&t.sec, &tm); + # strftime(buf, 1024, cfmt, &tm); + # res = tos2(buf); + return res +} + + +pub fn parse(s, fmt string) ?Time { + t := Time{} + cs := s.cstr() + cfmt := fmt.cstr() + ok := 0 + # struct tm tm; + # memset(&tm, 0, sizeof(struct tm)); + # ok = strptime(cs, cfmt, &tm); + if ok == 0 { + return error('time.parse: invalid time string') + } + # t.sec = mktime(&tm); + if t.sec < i64(0) { + return error('time.parse: invalid time string') + } + return t +} diff --git a/time/time_mac.v b/time/time_mac.v index 77efba9663..32bd49afc0 100644 --- a/time/time_mac.v +++ b/time/time_mac.v @@ -4,30 +4,66 @@ module time -//#flag -framework CoreServices -//#include -//#include +// TODO: nanosecond and monotonic +pub fn now() Time { + # time_t t = time(0); -// in ms -pub fn ticks() f64 { - panic('not implemented') -/* - t := i64(C.mach_absolute_time()) - # Nanoseconds elapsedNano = AbsoluteToNanoseconds( *(AbsoluteTime *) &t ); - # return (double)(* (uint64_t *) &elapsedNano) / 1000000; -*/ - return f64(0) + res := Time{} + # res.sec = t; + return res } -pub fn sleep(seconds int) { - C.sleep(seconds) +pub fn sleep(t Time) { + if t.sec > i64(0) { + C.sleep(t.sec) + } + if t.nsec > i32(0) { + C.usleep((t.nsec+i32(999))/i32(1000)) + } } -pub fn usleep(seconds int) { - C.usleep(seconds) +// TODO: Thread safety +fn (t Time) local() Info { + info := Info{} + # struct tm *tm = localtime(&t.sec); + # info.year = tm->tm_year + 1900; + # info.month = tm->tm_mon + 1; + # info.day = tm->tm_mday; + # info.hour = tm->tm_hour; + # info.minute = tm->tm_min; + # info.second = tm->tm_sec; + # info.yday = tm->tm_yday; + # info.wday = tm->tm_wday; + return info } -pub fn sleep_ms(seconds int) { - C.usleep(seconds * 1000) +// TODO: Thread safety +fn (t Time) utc() Info { + info := Info{} + # struct tm *tm = gmtime(&t.sec); + # info.year = tm->tm_year + 1900; + # info.month = tm->tm_mon + 1; + # info.day = tm->tm_mday; + # info.hour = tm->tm_hour; + # info.minute = tm->tm_min; + # info.second = tm->tm_sec; + # info.yday = tm->tm_yday; + # info.wday = tm->tm_wday; + return info } +// TODO: Thread safety +fn (t Time) format(fmt string) string { + res := '' + cfmt := fmt.cstr() + # char buf[1024]; + # struct tm *tm = localtime(&t.sec); + # strftime(buf, 1024, cfmt, tm); + # res = tos2(buf); + return res +} + +// TODO: Not implemented yet +pub fn parse(s string) ?Time { + return Time{} +} diff --git a/time/time_win.v b/time/time_win.v index fb0b151112..cc46b25b9d 100644 --- a/time/time_win.v +++ b/time/time_win.v @@ -4,21 +4,63 @@ module time -// in ms -fn ticks() double { - return C.GetTickCount() +// TODO: nanosecond and monotonic +pub fn now() Time { + # time_t t = time(0); + + res := Time{} + # res.sec = t; + return res } -fn sleep(seconds int) { - C._sleep(seconds * 1000) +pub fn sleep(t Time) { + if t.sec > i64(0) || t.nsec > i32(0) { + C.Sleep(i64(1000)*t.sec+(i64(t.nsec)+i64(999999))/i64(1000000)) + } } -fn usleep(seconds int) { - panic('usleep not impl') - // C._usleep(seconds) +// TODO: Thread safety +fn (t Time) local() Info { + info := Info{} + # struct tm *tm = localtime(&t.sec); + # info.year = tm->tm_year + 1900; + # info.month = tm->tm_mon + 1; + # info.day = tm->tm_mday; + # info.hour = tm->tm_hour; + # info.minute = tm->tm_min; + # info.second = tm->tm_sec; + # info.yday = tm->tm_yday; + # info.wday = tm->tm_wday; + return info } -fn sleep_ms(n int) { - C.Sleep(n) +// TODO: Thread safety +fn (t Time) utc() Info { + info := Info{} + # struct tm *tm = gmtime(&t.sec); + # info.year = tm->tm_year + 1900; + # info.month = tm->tm_mon + 1; + # info.day = tm->tm_mday; + # info.hour = tm->tm_hour; + # info.minute = tm->tm_min; + # info.second = tm->tm_sec; + # info.yday = tm->tm_yday; + # info.wday = tm->tm_wday; + return info } +// TODO: Thread safety +fn (t Time) format(fmt string) string { + res := '' + cfmt := fmt.cstr() + # char buf[1024]; + # struct tm *tm = localtime(&t.sec); + # strftime(buf, 1024, cfmt, tm); + # res = tos2(buf); + return res +} + +// TODO: Not implemented yet +pub fn parse(s string) ?Time { + return Time{} +} diff --git a/time/util.v b/time/util.v new file mode 100644 index 0000000000..317cd24e8b --- /dev/null +++ b/time/util.v @@ -0,0 +1,66 @@ +// Copyright (c) 2019 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 + +pub fn make(i Info) ?Time { + t := Time{} + # struct tm tm; + # tm.tm_year = i.year - 1900; + # tm.tm_mon = i.month - 1; + # tm.tm_mday = i.day; + # tm.tm_hour = i.hour; + # tm.tm_min = i.minute; + # tm.tm_sec = i.second; + # tm.tm_yday = i.yday; + # tm.tm_wday = i.wday; + # tm.tm_isdst = 0; + # t.sec = mktime(&tm); + if t.sec < i64(0) { + return error('time.make: invalid time infomation') + } + return t +} + +pub fn days(n int) Time { + return Time{ + sec: 86400*n + } +} + +pub fn hours(n int) Time { + return Time{ + sec: 3600*n + } +} + +pub fn minutes(n int) Time { + return Time{ + sec: 60*n + } +} + +pub fn seconds(n int) Time { + return Time{ + sec: n + } +} + +pub fn milliseconds(n int) Time { + return Time{ + nsec: 1000000*n + } +} + +pub fn microseconds(n int) Time { + return Time{ + nsec: 1000*n + } +} + +pub fn nanoseconds(n int) Time { + return Time{ + nsec: n + } +}