Каков наилучший способ сделать отметку времени? - PullRequest
1 голос
/ 07 октября 2010

Хорошо, так что я хотел бы сделать отметку времени до США ... М.С. было бы тоже хорошо ... но, глядя на это, я думаю, какие ЛУЧШИЕ ПРАКТИКИ при выполнении отметки времени? В этом случае я предполагаю, что используется код C / C ++. Я знаю, что внутренние часы имеют разные разрешения и тому подобное ... но мне интересно, о чем нужно помнить ... такие ответы помогут с тем, что я, возможно, еще не знаю.

Как должен выглядеть формат хорошего времени? Что вы думаете о функциях времени Posix? Я хочу иметь текстурное представление и внутреннее представление? Как проще всего это сделать, чтобы время можно было легко складывать и вычитать?

Ответы [ 5 ]

1 голос
/ 07 октября 2010

О чем следует помнить?

Поддерживайте синхронизацию ваших систем через NTP, чтобы вы могли коррелировать журналы из нескольких систем.

Если вы храните временную метку внутри, сохраняйте ее как количество секунд (возможно, с десятичными знаками для mS или uS).) с 1970 UTC.Это довольно стандартно, и при представлении вы можете легко преобразовать его в местное время в любом часовом поясе (полезно, если вам приходится иметь дело с несколькими часовыми поясами).Кроме того, в UTC нет перехода на летнее время, что позволяет избежать некоторых двусмысленностей (но не других, есть еще високосные секунды).

Если вам нужны метки времени для файла журнала, вы можете записать уже конвертированную метку времени в некоторыеудобочитаемый формат.UTC по-прежнему имеет свои преимущества при работе с несколькими часовыми поясами и позволяет избежать двусмысленности в переходе на летнее время.

Если вам нужно что-то более точное, рассмотрите libtai DJB или, в зависимости от ваших потребностей, POSIXclock_gettime () с CLOCK_MONOTONIC может быть достаточно.

1 голос
/ 07 октября 2010

На мой взгляд, лучший подход - сохранить представление на основе эпох как целое число. Наиболее стандартным является сохранение секунд с 1970 года. Поскольку вы хотите сохранить более высокое разрешение, вы можете увеличить его и оставить микросекунды или миллисекунды с 1970 года. Для этого вам нужно использовать как минимум 64-битное целое число ( долго долго).

Posix gettimeofday () даст вам разрешение вплоть до микросекунд, и вы можете комбинировать это с функцией gmtime_r (), чтобы получить оставшуюся часть штампа. Для окон я использую функцию GetSystemTime (), чтобы получить время в разрешении до миллисекунд (на самом деле, я думаю, что это десятки миллисекунд). Следующий фрагмент кода демонстрирует этот подход (не то, что мои единицы времени - это наносекунды).

  LgrDate rtn;
#ifdef _WIN32
  SYSTEMTIME sys;
  GetSystemTime(&sys);
  rtn.setDate(
     sys.wYear,
     sys.wMonth,
     sys.wDay);
  rtn.setTime(
     sys.wHour,
     sys.wMinute,
     sys.wSecond,
     sys.wMilliseconds*uint4(nsecPerMSec));
#else
  struct timeval time_of_day;
  struct tm broken_down;
  gettimeofday(&time_of_day,0);
  gmtime_r(
     &time_of_day.tv_sec,
     &broken_down);
  rtn.setDate(
     broken_down.tm_year + 1900,
     broken_down.tm_mon + 1,
     broken_down.tm_mday);
  rtn.setTime(
     broken_down.tm_hour,
     broken_down.tm_min,
     broken_down.tm_sec,
     time_of_day.tv_usec * nsecPerUSec);
#endif
  return rtn;
0 голосов
/ 07 октября 2010

Новый C++0x, среди его различных улучшений, наконец-то предоставляет полноценную библиотеку time.

Он был разработан в основном для поддержки thread (чтобы выразить ограничения продолжительности / времени дляразличные try_lock и др.), но это настоящая блестящая жемчужина.Вы можете найти оригинальное предложение здесь и запись Бьярне о нем здесь .

Очевидно, что оно зависит от правильной синхронизации вашей системы, если вы хотите сравнить это время свнешние источники: используйте NTP.Я также рекомендовал бы использовать время UTC, проще выразить все время в общем часовом поясе, без перехода на летнее время.

Что касается самого представления, я бы выбрал удобочитаемое человеком.Для машины так же просто разобрать любой формат, но не для человека, и кто занимается расследованием?

[1] 2010/10/07 06:54:36.123456
[2] 2010 OCT 07 06:54:36.123456
[3] 86456156456.123456          // garbage I made up ;)

Второй формат позволяет избавиться от неоднозначности месяца безо всякой путаницы.Это мой любимый, но я чаще всего вижу первый.

0 голосов
/ 07 октября 2010

Нет переносимых функций времени, которые надежно обеспечивают разрешение более 10 мс. Функция gettimeofday (), на которую ссылаются другие респонденты, имеет системно-зависимое разрешение, которое, как я полагаю, обычно составляет 1 или 10 мс. Кроме того, даже 90% непереносимых функций времени будет включать в себя отключение до 0 (тысячи тактов), что означает, что вам может потребоваться 1-2 мс просто для выполнения вызова функции!

Единственный метод, который работает на всех платформах Intel, обеспечивает разрешение менее микросекунды и стоит менее 10 наносекунд на вызов - это инструкция по сборке 'rdtsc' (или встроенная функция __rdtsc ()).

0 голосов
/ 07 октября 2010

См. Свою страницу руководства для gettimeofday

int gettimeofday(struct timeval *tp, void *);

long    tv_sec;    /* seconds since Jan. 1, 1970 */
     long    tv_usec;   /* and microseconds */

вы можете хранить времена как struct timeval, есть макросы для выполнения сложения и вычитания со значениями struct timeval. Вы можете использовать ctime (tv_sec), чтобы получить строку ascii. Если вам нужно создать строку с помощью usec, попробуйте что-то вроде этого:

char *now(void)  /* time to /1000ths of a second */
{
    struct timeval tv={0,0};
    int i=gettimeofday(&tv, NULL);
    static char retval[64]={0x0};
    char tmp[16]={0x0};

    if(i<0)
        return NULL;
    sprintf(tmp, "%.3f", (double)tv.tv_usec / (double)1000000);
    strftime(retval, sizeof(retval),
             "%Y-%m-%d %H:%M:%S.",
             localtime(&tv.tv_sec));
    strcat(retval, &tmp[2]);

    return retval;
}
...