0

I have broken-down time which I then convert to UNIX timestamp in UTC and without DST with _mkgmtime instead of mktime(which applies the local timezone). This works fine. What I now want is to convert the UNIX timestamp generated back to broken-down time exactly the same with no DST/TimeZone changes. I tried using strftime() but it converts to local timezone. The same goes with localtime().

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

int main() {
    struct tm info;
    char buffer[80];
    
    info.tm_year = 2022 - 1900;
    info.tm_mon = 5 - 1;
    info.tm_mday = 19;
    info.tm_hour = 15;
    info.tm_min = 3;
    info.tm_sec = 0;
    info.tm_isdst = 0;
    
    uint32_t time_passed_utc = _mkgmtime(&info);
    printf("time_passed_utc uint32: %lu\n", time_passed_utc); // this returns correctly "1652972580"
    strftime(buffer, sizeof(buffer), "time_passed_utc-> %c", &info );
    printf(buffer); // this returns correctly "05/19/22 15:03:00"
    
    printf("\n\n");
    
    time_t rawtime = 1652972580;
    
    struct tm  ts;
    char       buf[80];
    
    // Format time, "ddd yyyy-mm-dd hh:mm:ss zzz"
    ts = *localtime(&rawtime);
    ts.tm_isdst = 0; // no DST setting
    strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
    printf("%s\n", buf);  // returns incorrectly "Thu 2022-05-19 18:03:00 E. Europe Standard Time" -> should have been "2022-05-19 15:03:00"
    
    return(0);
}
Cris
  • 4,004
  • 16
  • 50
  • 74
  • 4
    Maybe you want `gmtime` instead of `localtime`? – dbush May 19 '22 at 13:14
  • [This question](https://stackoverflow.com/questions/40584032/convert-unix-timestamp-s-to-day-of-week-in-c) seems to have all your answers – Jean-Pascal J. May 19 '22 at 13:16
  • You might try adjusting the TZ environment variable as well: https://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/ – Aconcagua May 19 '22 at 13:16
  • 1
    You can find the documentation for these C standard library functions if you run `man [function]` (Ex: `man localtime`) in the Linux shell. You may find it helpful to just try viewing the `man` pages when you are unsure. – Locke May 19 '22 at 13:18
  • @Jean-PascalJ. Not really, that question is about C++ and the accepted answer does not translate to C. – Cheatah May 19 '22 at 13:20
  • dbush, with gmtime() it return hour 13 instead of 15. – Cris May 19 '22 at 13:25
  • Locke, I don't have access to a Linux shell. – Cris May 19 '22 at 13:27
  • @Cris I'm getting 15. Are you sure you didn't change something else? – dbush May 19 '22 at 13:43

1 Answers1

4

I always think about questions like these using something like this table. To convert from something in the first column, to something in one of the other columns, call the indicated function.

time_t struct tm (UTC) struct tm (local) string custom string
time_t - gmtime localtime ctime n/a
struct tm (UTC) timegm * - n/a asctime strftime
struct tm (local) mktime n/a - asctime strftime

You want to convert a time_t to a struct tm in UTC, so the function you want is gmtime.

I didn't include rows for converting from strings, because the functions to do so aren't as standard. Perhaps the best-known is strptime, which converts from a custom string back to a struct tm, making it more or less the inverse of strftime.

(In fairness, timegm isn't perfectly standard, either.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • With gmtime I get hour 13 instead of 15 from rawtime = 1652972580; – Cris May 19 '22 at 13:37
  • 1
    @Cris I can't reproduce that. I get 15, as you expected. Something funny is going on. – Steve Summit May 19 '22 at 13:40
  • Nevermind, it appears to work! Thank you! – Cris May 19 '22 at 13:43
  • If I have a UNIX time generated by mktime (since I do not have access to _mkgmtime), how do I convert it to broken down time without gmtime (since I don't have access to it either)? – Cris Jun 02 '22 at 12:18
  • @Cris I take it you have `localtime` but not `gmtime`, and you want to convert a `time_t` value in UTC into a broken-down time, also in UTC? Which is precisely what `gmtime` would do, if you had it? First question: Does `struct tm` on your system have a field `tm_gmtoff` or `__tm_gmtoff` or `__tm_gmtoff__`? – Steve Summit Jun 02 '22 at 15:31
  • @Cris Second, side question: *Why* does your system not have `gmtime`? Is this a stripped-down or embedded system of some kind? – Steve Summit Jun 02 '22 at 15:32