Как напечатать время в формате: 2009‐08‐10 18: 17: 54.811

97

Как лучше всего распечатать время на C в формате 2009‐08‐10 
18:17:54.811?

Доминик Боу-Самра
источник

Ответы:

109

Используйте strftime () .

#include <stdio.h>
#include <time.h>

int main()
{
    time_t timer;
    char buffer[26];
    struct tm* tm_info;

    timer = time(NULL);
    tm_info = localtime(&timer);

    strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
    puts(buffer);

    return 0;
}

Что касается миллисекунд, взгляните на этот вопрос. Как измерить время в миллисекундах с помощью ANSI C?

Хамид Назари
источник
Теперь это даже лучший ответ, и он помогает понять, как обрабатывать миллисекундную часть. Я думаю, ваш буфер теперь немного длиннее, чем должен быть.
Джек Келли
16
Лучше быть длиннее, чем короче :-)
paxdiablo
Замечательный ответ. Я мог делать все на PHP, но знал, что все это уже есть в C. Спасибо.
Виджай Кумар Канта
1
Возможно, линейка time(&timer)скорее должна быть timer = time(NULL);, по крайней мере, для Linux. The tloc argument is obsolescent and should always be NULL in new code. When tloc is NULL, the call cannot fail.
Антонин Десимо
6
Ответ определенно неверен, по крайней мере, в одном случае (Linux), поскольку "struct tm", используемая localtime (), не содержит информации о времени ниже секунд. Вместо «struct timeval», используемой gettimeofday (), есть микросекунды, которые, деленные на 1000, дают миллисекунды. Все эти голоса на самом деле неверны и вводят в заблуждение! Если только кто-то не сообщает, в какой архитектуре вы получите подробную информацию о времени ниже второй с помощью "struct tm".
EnzoR
32

Приведенные выше ответы не полностью отвечают на вопрос (в частности, на миллисекундную часть). Мое решение - использовать gettimeofday до strftime. Обратите внимание на осторожность, чтобы не округлять миллисекунды до «1000». Это основано на ответе Хамида Назари.

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>

int main() {
  char buffer[26];
  int millisec;
  struct tm* tm_info;
  struct timeval tv;

  gettimeofday(&tv, NULL);

  millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
  if (millisec>=1000) { // Allow for rounding up to nearest second
    millisec -=1000;
    tv.tv_sec++;
  }

  tm_info = localtime(&tv.tv_sec);

  strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", tm_info);
  printf("%s.%03d\n", buffer, millisec);

  return 0;
}
Крис
источник
gettimeofdayнедоступно для реализаций Windows
Мендес,
Пожалуйста, добавьте параметры '-lm' при его сборке.
skysign
3
Я думаю, что буфера [24] достаточно, причина такая, как показано ниже, ГГГГ: ММ: ДД ЧЧ: ММ: СС.ммм + '\ 0', равно 24.
skysign
@Mendes, почему упоминается Windows? Речь идет о простом языке C. Это лучший ответ (хотя и не правильный), несмотря на все эти неправильные голоса!
EnzoR
2
user3624334: Нет, вы не понимаете код. Есть только одна просьба о времени. Я предполагаю, что вы имеете в виду вызов местного времени - он просто переформатирует вывод gettimeofday.
Крис
12

time.hопределяет strftimeфункцию, которая может дать вам текстовое представление, time_tиспользуя что-то вроде:

#include <stdio.h>
#include <time.h>
int main (void) {
    char buff[100];
    time_t now = time (0);
    strftime (buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime (&now));
    printf ("%s\n", buff);
    return 0;
}

но это не даст вам субсекундного разрешения, так как оно недоступно из time_t. Он выводит:

2010-09-09 10:08:34.000

Если вы действительно ограничены спецификациями и не хотите промежуток между днем ​​и часом, просто удалите его из строки формата.

Paxdiablo
источник
+1 за уловку заполнения дисплея с точностью до миллисекунды. Однажды у меня был заказчик, который хотел, чтобы я это сделал, но с ненулевыми цифрами, поэтому казалось, что в этом есть значимость. Я отговорил его, но согласился поставить нули.
RBerteig
4
Один мой друг (не я, конечно) однажды применил похожий трюк - они сохранили статику, содержащую последнюю секунду и «миллисекунду». Если второе не изменилось по сравнению с прошлым разом, они просто добавили случайное значение от 1 до 200 в миллисекунды (конечно, убедившись, что оно не превышает 999 - фактический максимум для rand () всегда был минимальным из 200 и половина расстояния до 999). Если второй действительно изменился, они просто установили миллисекунду на 0 перед добавлением. Хорошие, казалось бы, случайные, но правильно упорядоченные миллисекунды, и покупатель не был в этом мудрее :-)
paxdiablo
5

Следующий код печатается с точностью до микросекунд. Все , что нужно сделать , это использовать gettimeofdayи strftimeна tv_secи Append tv_usecк построенной строке.

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int main(void) {
    struct timeval tmnow;
    struct tm *tm;
    char buf[30], usec_buf[6];
    gettimeofday(&tmnow, NULL);
    tm = localtime(&tmnow.tv_sec);
    strftime(buf,30,"%Y:%m:%dT%H:%M:%S", tm);
    strcat(buf,".");
    sprintf(usec_buf,"%dZ",(int)tmnow.tv_usec);
    strcat(buf,usec_buf);
    printf("%s",buf);
    return 0;
}
Натарадж
источник
2

Вы можете использовать strftime, но у struct tmнего нет разрешения на доли секунды. Я не уверен, что это абсолютно необходимо для ваших целей.

struct tm tm;
/* Set tm to the correct time */
char s[20]; /* strlen("2009-08-10 18:17:54") + 1 */
strftime(s, 20, "%F %H:%M:%S", &tm);
Джек Келли
источник
2

трюк:

    int time_len = 0, n;
    struct tm *tm_info;
    struct timeval tv;

    gettimeofday(&tv, NULL);
    tm_info = localtime(&tv.tv_sec);
    time_len+=strftime(log_buff, sizeof log_buff, "%y%m%d %H:%M:%S", tm_info);
    time_len+=snprintf(log_buff+time_len,sizeof log_buff-time_len,".%03ld ",tv.tv_usec/1000);
Андрей Мельников
источник
1
Пожалуйста, поясните, почему это работает. и что именно происходит.
Радж Камаль,
Все то же, что и в примерах выше, но только более эффективно. `time_len + = snprintf (log_buff + time_len, sizeof log_buff-time_len," log var is =% s ", logvar); int ret = запись (log_fd, log_buff, time_len); `
Андрей Мельников
Откуда мне импортировать gettimeofday?
AndreyP
1

Ни одно из решений на этой странице у меня не сработало, я перепутал их и заставил работать с Windows и Visual Studio 2019, вот как:

#include <Windows.h>
#include <time.h> 
#include <chrono>

static int gettimeofday(struct timeval* tp, struct timezone* tzp) {
    namespace sc = std::chrono;
    sc::system_clock::duration d = sc::system_clock::now().time_since_epoch();
    sc::seconds s = sc::duration_cast<sc::seconds>(d);
    tp->tv_sec = s.count();
    tp->tv_usec = sc::duration_cast<sc::microseconds>(d - s).count();
    return 0;
}

static char* getFormattedTime() {
    static char buffer[26];

    // For Miliseconds
    int millisec;
    struct tm* tm_info;
    struct timeval tv;

    // For Time
    time_t rawtime;
    struct tm* timeinfo;

    gettimeofday(&tv, NULL);

    millisec = lrint(tv.tv_usec / 1000.0);
    if (millisec >= 1000) 
    {
        millisec -= 1000;
        tv.tv_sec++;
    }

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", timeinfo);
    sprintf_s(buffer, 26, "%s.%03d", buffer, millisec);

    return buffer;
}

Результат:

2020: 08: 02 06: 41: 59.107

2020: 08: 02 06: 41: 59.196

PinnedObject
источник