Konwersja Unix timestamp na "ludzką" formę

0

Potrzebuję pobrać z InfluxDB dane, z tym że czas zapisywany jest w bazie jako ilość sekund od 1-01-1970 godzina 0000 czasu UTC.
Program do konwersji na "ludzką formę" wygląda tak:

#include <stdio.h>
#include <time.h>
#include <locale.h>
int main (void) {
time_t tm = 1556746799;
printf ("%s", ctime (&tm));
return 0;
}

Nic prostszego chyba być nie może. Ale w wyniku działania tego programu o ile występuje czas letni, to data (nie godzina!!) jest o jeden dzień większa. Wynik działania programu daje:

Wed May 1 2359 2019

A powinien być 31 kwietnia. Godzina się zgadza, przeliczył według czasu letniego. Ale jeżeli data jest z czasu zimowego, to jest konwertowana prawidłowo. Program kompiluję na Linux Mageia , fork od RHL. Poprawność konwersji sprawdzałem za pomocą dostępnych w internecie konwerterów on-line.
Spotkał się któryś z Szanownych Kolegów z czymś takim? Jaki błąd robię?

0

Nie znam się to się wypowiem.

Wed May 1 2359 2019

A próbowałeś konwertować inną, nie brzegową godzinę? Np April 31 2230

0

A jakie masz ustawienia strefy czasowej/locale? Bo to wygląda na tego typu problem. Co dają kombinacje z tzset i okolicami?t

0

Oj, próbowałem wiele różnych dat/czasów. Letni, zimowy, sprzed kilku lat, lub kilka lat naprzód. W sumie nie skłamię jak powiem - kilkadziesiąt. Próbowałem różne warianty. Brzegowe godziny i inne. Zawsze to samo.

0
alagner napisał(a):

A jakie masz ustawienia strefy czasowej/locale? Bo to wygląda na tego typu problem. Co dają kombinacje z tzset i okolicami?t

Tak, próbowałem dodać do kodu następujące wpisy:

setlocale (LC_ALL, "pl_PL");
setlocale (LC_ALL, "");

Ale nic to nie zmieniło

0

to jest problem strefy czasowej.
ctime wykonuje konwersję do strefy czasowej charakterystycznej dla danej maszyny. Czyli dla Polski to jest czas letni to UTC+2.
gmtime zwraca czas absolutny (UTC).
Locale tutaj ma jedynie wpływ na format daty, a nie strefę czasową.

1556746799 daje mi 05/01/2019 @ 9:39pm (UTC) - https://www.unixtimestamp.com/index.php
więc nie wiem skąd ci się wzięło, że powinno być 31 kwietnia. Nie ma strefy czasowej (UTC-22), która by dała taką datę tego timestamp.
A wynik, który wypluwa ci kod zgadza się z tym co podaje strona (po uwzględnieniu strefy czasowej Polski).

A jeszcze jedno. Twój kod to UB. Nigdzie nie jest powiedziane, że time_t reprezentuje unix timestemp.
Standard nie definiuje ani jednostki czasu, ani EPOC time.

0

Hmmm. To może problem leży w konwersji z czasu "ludzkiego" na Unix timesamp. Oto program który to robi:

#define _GNU_SOURCE
#include <stdio.h>
#include <time.h>
#include <string.h>
int dst = 0 ; // Czy jest DST czy nie
int month;
int previousSunday = 0;
int days_diff = 0;
int month_days_1 = 31;
int month_days_2 = 31;
int main(void) {
struct tm tm;
time_t t;
char s[20]="2019-04-31,2359";
if (strptime(s, "%Y-%m-%d,%H:%M:%S", &tm)==NULL) printf ("ERROR-1\n");
month=tm.tm_mon + 1;
if (month < 3 || month > 10) {
dst=0; }
else {
dst=1;
if (month==3 && tm.tm_mday > 23) {
previousSunday = tm.tm_mday - tm.tm_wday;
days_diff = month_days_1 - previousSunday;
if (days_diff >= 6) dst=0;
}
if (month==10 && tm.tm_mday > 23) {
previousSunday = tm.tm_mday - tm.tm_wday;
days_diff = month_days_2 - previousSunday;
if (days_diff <= 6) dst=0;
}
}
tm.tm_isdst = -1;
printf("year: %d; month: %d; day: %d;\n", tm.tm_year + 1900, month, tm.tm_mday);
printf("hour: %d; minute: %d; second: %d\n", tm.tm_hour, tm.tm_min, tm.tm_sec);
printf("week day: %d; year day: %d; Sunday: %d; DST %d; Days %d\n", tm.tm_wday, tm.tm_yday, previousSunday, dst, days_diff);
t = mktime(&tm);
printf("seconds since the Epoch: %ld\n", (long) t);
}

co daje w wyniku:

year: 2019; month: 4; day: 31;
hour: 23; minute: 39; second: 59
week day: 3; year day: 120; Sunday: 0; DST 1; Days 0
seconds since the Epoch: 1556746799

Może w tym programie leży problem?

1

Problem rozwiązałem. Tak właściwie chodziło mi o wprowadzanie danych do InfluxDB. Dokumentacja stanowi że jak w insert/select wpiszę tz=('Europe/Warsaw') to baza sama przeliczy w te i we wte czas lokalny na UTC wyrażony w "Unix Epoch" czyli ilości sekund od 1 stycznia 1970 roku. Bo tak to jest zapisywane w bazie. Tyle że nie działało. Wszystko mam zainstalowane na QNAP 4 core/16 GB RAM. Przyczyną nie działania było to że Tajwańczycy nie przewidują istnienia takich miast jak Warszawa czy Bruksela ale przewidują istnienie Sarajewa czy Paryża. Zmieniłem w kwerendach Warsaw na Paris i zadziałało. Teraz przeliczania dokonuje sama baza i wszystko jest OK. Następnie skopiowałem definicje TZ z Linuxa na QNAP i teraz mogę używać składni Europe/Warsaw.
Ot problem leżał zupełnie gdzie indziej.
Niemniej bardzo dziękuję Kolegom za współpracę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1