shithub: femtolisp

ref: 8b59a493d6b5e51811321339450bddbe2aa56c24
dir: /llt/timefuncs.c/

View raw version
#ifdef PLAN9
#include <u.h>
#include <libc.h>
#else
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <unistd.h>
#endif

#include "dtypes.h"
#include "timefuncs.h"

#if defined(PLAN9)
double floattime(void)
{
    return (double)nsec() / 1.0e9;
}
#else
double tv2float(struct timeval *tv)
{
    return (double)tv->tv_sec + (double)tv->tv_usec/1.0e6;
}

double diff_time(struct timeval *tv1, struct timeval *tv2)
{
    return tv2float(tv1) - tv2float(tv2);
}
#endif

// return as many bits of system randomness as we can get our hands on
uint64_t i64time(void)
{
    uint64_t a;
#if defined(PLAN9)
    a = nsec();
#else
    struct timeval now;
    gettimeofday(&now, NULL);
    a = (((uint64_t)now.tv_sec)<<32) + (uint64_t)now.tv_usec;
#endif

    return a;
}

double clock_now(void)
{
#if defined(PLAN9)
    return floattime();
#else
    struct timeval now;

    gettimeofday(&now, NULL);
    return tv2float(&now);
#endif
}

void timestring(double seconds, char *buffer, size_t len)
{
#ifdef PLAN9
    Tm tm;
    snprint(buffer, len, "%τ", tmfmt(tmtime(&tm, seconds, tzload("local")), nil));
#elif defined(LINUX) || defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD)
    time_t tme = (time_t)seconds;

    char *fmt = "%c"; /* needed to suppress GCC warning */
    struct tm tm;

    localtime_r(&tme, &tm);
    strftime(buffer, len, fmt, &tm);
#else
    time_t tme = (time_t)seconds;

    static char *wdaystr[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
    static char *monthstr[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
                               "Sep","Oct","Nov","Dec"};
    struct tm *tm;
    int hr;

    tm = localtime(&tme);
    hr = tm->tm_hour;
    if (hr > 12) hr -= 12;
    if (hr == 0) hr = 12;
    snprintf(buffer, len, "%s %02d %s %d %02d:%02d:%02d %s %s",
             wdaystr[tm->tm_wday], tm->tm_mday, monthstr[tm->tm_mon],
             tm->tm_year+1900, hr, tm->tm_min, tm->tm_sec,
             tm->tm_hour>11 ? "PM" : "AM", "");
#endif
}

#if defined(LINUX) || defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD)
extern char *strptime(const char *s, const char *format, struct tm *tm);
double parsetime(const char *str)
{
    char *fmt = "%c"; /* needed to suppress GCC warning */
    char *res;
    time_t t;
    struct tm tm;

    res = strptime(str, fmt, &tm);
    if (res != NULL) {
        tm.tm_isdst = -1; /* Not set by strptime(); tells mktime() to determine
                            whether daylight saving time is in effect */
        t = mktime(&tm);
        if (t == ((time_t)-1))
            return -1;
        return (double)t;
    }
    return -1;
}
#elif defined(PLAN9)
double parsetime(const char *str)
{
    Tm tm;

    if (tmparse(&tm, "?WWW, ?MM ?DD hh:mm:ss ?Z YYYY", str, tzload("local"), nil) == nil)
        return -1;

    return tmnorm(&tm);
}
#else
// TODO
#endif

void sleep_ms(int ms)
{
    if (ms == 0)
        return;

#if defined(PLAN9)
    sleep(ms);
#else
    struct timeval timeout;

    timeout.tv_sec = ms/1000;
    timeout.tv_usec = (ms % 1000) * 1000;
    select(0, NULL, NULL, NULL, &timeout);
#endif
}