Uzyskasz znacznik czasu w C w mikrosekundach?

Jak uzyskać znacznik czasu mikrosekund w C?

Próbuję zrobić:

struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_usec;

Ale to zwraca jakąś nonsensowną wartość, że jeśli dostanę dwa znaczniki czasu, drugi może być mniejszy lub większy od pierwszego (drugi powinien zawsze być większy). Czy jest możliwe przekształcenie magicznej liczby całkowitej zwracanej przez gettimeofday na normalną liczbę, z którą można faktycznie pracować?

 32
Author: Kristina Brooks, 2011-04-29

7 answers

Musisz też dodać w sekundach:

unsigned long time_in_micros = 1000000 * tv.tv_sec + tv.tv_usec;

Zauważ, że potrwa to tylko ok. 232/106 =~ 4295 sekund, czyli około 71 minut (w typowym systemie 32-bitowym).

 41
Author: unwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-02 02:38:15

Masz dwie możliwości uzyskania znacznika czasu mikrosekundy. Pierwszym (i najlepszym) wyborem jest użycie typu timeval bezpośrednio:

struct timeval GetTimeStamp() {
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return tv;
}

Drugim i dla mnie mniej pożądanym wyborem jest zbudowanie uint64_t z timeval:

uint64_t GetTimeStamp() {
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return tv.tv_sec*(uint64_t)1000000+tv.tv_usec;
}
 18
Author: Robᵩ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-28 16:53:06

Struct timeval zawiera dwa składniki, drugi i mikrosekundę. Znacznik czasu z dokładnością mikrosekund jest reprezentowany jako sekundy od epoki przechowywanej w polu tv_sec i ułamkowe mikrosekundy w tv_usec. Dlatego nie można po prostu ignorować tv_sec i oczekiwać sensownych rezultatów.

Jeśli używasz Linuksa lub * BSD, możesz użyć timersub (), aby odjąć dwie wartości STRUCT timeval, które mogą być tym, czego chcesz.

 8
Author: janneb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 14:19:05

Ale to zwraca jakąś nonsensowną wartość że jeśli dostanę dwa znaczniki czasu, drugi może być mniejszy lub większy niż pierwsza (druga powinna zawsze bądź większy).

Dlaczego tak myślisz? Wartość jest prawdopodobnie OK. Jest to taka sama sytuacja jak w przypadku sekund i minut – kiedy mierzysz czas w minutach i sekundach, liczba sekund spada do zera, gdy osiągnie sześćdziesiąt.

Aby przekonwertować zwróconą wartość na liczbę "liniową" można pomnóż liczbę sekund i dodaj mikrosekundy. Ale jeśli policzę poprawnie, jeden rok to około 1e6*60*60*24*360 µsec, a to oznacza, że będziesz potrzebował więcej niż 32 bitów, aby zapisać wynik:

$ perl -E '$_=1e6*60*60*24*360; say int log($_)/log(2)'
44

To prawdopodobnie jeden z powodów, aby podzielić oryginalną zwróconą wartość na dwie części.

 2
Author: zoul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 14:16:12

Timespec_get z C11 zwraca maksymalnie nanosekundy, zaokrąglone do rozdzielczości implementacji.

#include <time.h>
struct timespec ts;
timespec_get(&ts, TIME_UTC);
struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};

Więcej szczegółów tutaj: https://stackoverflow.com/a/36095407/895245

 2
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:40

Najpierw musimy poznać zakres mikrosekund tj. od 000_000 do 999_999 (1000000 mikrosekund jest równe 1sekundzie). tv. tv_usec zwróci wartość od 0 do 999999, a nie 000000 do 999999, więc używając go z sekundami możemy otrzymać 2.1 sekundy zamiast 2.000001 sekund, ponieważ gdy tylko mówimy o tv_usec 000001 jest zasadniczo 1. Its better if you insert

if(tv.tv_usec<10)
{
 printf("00000");
} 
else if(tv.tv_usec<100&&tv.tv_usec>9)// i.e. 2digits
{
 printf("0000");
}

I tak dalej...

 0
Author: Osaid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-26 16:07:17

Użyj unsigned long long (tj. 64-bitowej jednostki) do reprezentowania czasu systemowego:

typedef unsigned long long u64;

u64 u64useconds;
struct timeval tv;

gettimeofday(&tv,NULL);
u64useconds = (1000000*tv.tv_sec) + tv.tv_usec;
 0
Author: user6269400,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-12 16:12:38