13 comments

  • chikere2327 小时前
    Is it a struggle though?

    They needed to have a locale matching the language of the localised time string they wanted to parse, they needed to use strptime to parse the string, they needed to use timegm() to convert the result to seconds when seen as UTC. The man pages pretty much describe these things.

    The interface or these things could certainly be nicer, but most of the things they bring up as issues aren't even relevant for the task they're trying to do. Why do they talk about daylight savings time being confusing when they're only trying to deal with UTC which doesn't have it?

    • johnisgood7 小时前
      It is not.

        int main(void) {
          struct tm tm = {0}; 
          const char *time_str = "Mon, 20 Jan 2025 06:07:07 GMT"; 
          const char *fmt = "%a, %d %b %Y %H:%M:%S GMT"; 
      
          // Parse the time string
          if (strptime(time_str, fmt, &tm) == NULL) {
              fprintf(stderr, "Error parsing time\n");
              return 1;
          }
      
          // Convert to Unix timestamp (UTC)
          time_t timestamp = timegm(&tm);
          if (timestamp == -1) {
              fprintf(stderr, "Error converting to timestamp\n");
              return 1;
          }
      
          printf("Unix timestamp: %ld\n", timestamp);
          return 0;
        }
      
      It is a C99 code snippet that parses the UTC time string and safely converts it to a Unix timestamp and it follows best practices from the SEI CERT C standard, avoiding locale and timezone issues by using UTC and timegm().

      You can avoids pitfalls of mktime() by using timegm() which directly works with UTC time.

      Where is the struggle? Am I misunderstanding it?

      Oh by the way, must read: https://www.catb.org/esr/time-programming/ (Time, Clock, and Calendar Programming In C by Eric S. Raymond)

      • paxcoder6 小时前
        I can't find `timegm` neither in the C99 standard draft nor in POSIX.1-2024.

        The first sentence of your link reads:

        >The C/Unix time- and date-handling API is a confusing jungle full of the corpses of failed experiments and various other traps for the unwary, many of them resulting from design decisions that may have been defensible when the originals were written but appear at best puzzling today.

        • chikere2324 小时前
          https://man7.org/linux/man-pages/man3/timegm.3.html

          It's not posix, but it's pretty available

        • johnisgood4 小时前
          Yeah, you're correct that `timegm` is neither part of the C99 standard nor officially specified in POSIX.1-2024 but it is widely supported in practice on many platforms, including glibc, musl, and BSD systems which makes it a pragmatic choice in environments where it is available. Additionally, it is easy to implement it in a portable way when unavailable.

          So, while `timegm` is not standardized in C99 or POSIX, it is a practical solution in most real-world environments, and alternatives exist for portability, and thus: handling time in C is not inherently a struggle.

          As for the link, it says "You may want to bite the bullet and use timegm(3), even though it’s nominally not portable.", but see what I wrote above.

          • oofabz4 小时前
            timegm() is even available on Haiku
    • pif7 小时前
      What's a man page? [cit]
  • d_burfoot6 小时前
    My personal rule for time processing: use the language-provided libraries for ONLY 2 operations: converting back and forth between a formatted time string with a time zone, and a Unix epoch timestamp. Perform all other time processing in your own code based on those 2 operations, and whenever you start with a new language or framework, just learn those 2.

    I've wasted so many dreary hours trying to figure out crappy time processing APIs and libraries. Never again!

  • 1970-01-017 小时前
    13 more years to go until the 2038 problem.

    Surely we'll have everything patched up by then..

    • ahubert7 小时前
      wow that is dedication 1970-01-01! :-)
  • rstuart41335 小时前
    For those skimmimg the problem is mktime() returns local time, and they want it in UTC. So you need to subtract the timezone used, but the timezone varies by date you feed mktime() and there is no easy way to determime it.

    If you are happy for the time to perhaps be wrong around the hours timezone changes, this is an easy hack:

        import time
        def time_mktime_utc(_tuple):
            result = time.mktime(_tuple[:-1] + (0,))
            return result * 2 - time.mktime(time.gmtime(result))
    
    If you are just using it for display this is usually fine as time zone changes are usually timed to happen when nobody is looking.
    • chikere2324 小时前
      That is not really the problem.

      mktime() parses the time string which lacks any information on time zones

      then the article uses timegm() to convert it to unixtime on the assumption that it was in UTC

      also it's about C

  • p0w3n3d6 小时前
    I think that time handling is the most hard thing in the world of programming.

    Explanation: you can learn heap sort or FFT or whatever algorithm there is and implement it. But writing your own calendar from scratch, that will do for example chron job on 3 am in the day of DST transition, that works in every TZ, is a work for many people and many months if not years...

    • timewizard6 小时前
      Time handling is exceptionally easy. Time zone handling is hard. It doesn't help that the timezone database isn't actually designed to make this any easier.
      • p0w3n3d5 小时前
        Meanwhile I edited my comment but we're still agreeing. And adding them for example to embedded systems is additional pain. Example: tram or train electronic boards / screens
      • DougN72 小时前
        I don’t know. I’ve written that seemed like obvious simple code that got tripped up with the 25 hour day on DST transition. That’s when I learned to stick to UTC.
  • jonstewart6 小时前
    The headline doesn’t match the article. As it points out, C++20 has a very nice, and portable, time library. I quibble with the article here, though: in 2025, C++20 is widely available.
    • spacechild13 小时前
      Damn, I didn't notice that C++20 added a whole bunch of new features to the std::chrono library! Nice!
    • jeffbee5 小时前
      Indeed. The article should be retitled "C still useless in 2025, including time handling".
  • 8 小时前
    undefined
  • richrichie4 小时前
    > give us some truly excellent code that we really don’t deserve

    Why such self flagellation?

  • sylware8 小时前
    Until you understand that the core of unix time is the "day", in the end, you only need to know the first leap year (If I recall properly it is 1972), then you have to handle the "rules" of leap years, and you will be ok (wikipedia I think, don't use google anymore since they now force javascript upon new web engines).

    I did write such code in RISC-V assembly (for a custom command line on linux to output the statx syscall output). Then, don't be scared, with a bit of motivation, you'll figure it out.

    • DamonHD6 小时前
      The core of the UNIX time is seconds since epoch, nothing else. 'Day' has no special place at all. There are calendars for converting to and from dates, including Western-style, but the days in those calendars vary in length because of daylight saving switches and leap seconds for example.
      • Kwpolska6 小时前
        UNIX time ignores leap seconds, so every day is exactly 86400 seconds, and every year is either 365*86400 or 366*86400 seconds. This makes converting from yyyy-mm-dd to UNIX time quite easy, as you can just do `365*86400*(yyyy-1970) + leap_years*86400` to get to yyyy-01-01.
        • XorNot4 小时前
          Well yes, in the sense that not all Unix epoch seconds are equally long...
  • udidnmem8 小时前
    You cannot since it's missing time zone
    • RHSeeger8 小时前
      UTC is a timezone, though. Or am I misunderstanding what you're saying?
      • cvadict8 小时前
        That is fine as long as the input / output is always in UTC... but at the end of the day you often want to communicate that timepoint to a human user (e.g. an appointment time, the time at which some event happened, etc.), which is when our stupid monkey brains expect the ascii string you are showing us to actually make sense in our specific locale (including all of the warts each of those particular timezones have, including leap second, DST, etc.)
      • jxjsndbxbd8 小时前
        UTC would be marked as +Z

        Without any marking, it could be anything

        • loeg8 小时前
          The article explicitly mentions UTC all over the place. It's UTC.
        • DamonHD6 小时前
          No '+'.

          Noon UTC is "12:00Z".

  • emcell7 小时前
    again, one of the many reasons i dont code in c or cpp anymore
    • npalli3 小时前
      Jeez, read the article. C++20 has such an elegant solution that it has him swooning.

      Being truly luxurious, the tz library supports using not just your operating system’s time zone databases, which might lack crucial leap second detail, but can also source the IANA tzdb directly. This allows you to faithfully calculate the actual duration of a plane flight in 1978 that not only passed through a DST change, but also an actual leap second. I don’t swoon easily, but I’m swooning.

    • ta-1956786 小时前
      Was waiting for rustaceans to come and base c/cpp.. didn’t take long
      • Dylan168071 小时前
        They have five comments ever. What makes you think they use rust?
    • pif7 小时前
      And the fox said: "These grapes are sour".
      • Dylan168076 小时前
        That makes no sense in this context. What's the situation you're imagining where they wanted to use C but something else prevented them so they made up an excuse to call C bad?

        You know sometimes people just dislike things, right?

  • 6 小时前
    undefined
  • zX41ZdbW7 小时前
    The first rule of thumb is to never use functions from glibc (gmtime, localtime, mktime, etc) because half of them are non-thread-safe, and another half use a global mutex, and they are unreasonably slow. The second rule of thumb is to never use functions from C++, because iostreams are slow, and a stringstream can lead to a silent data loss if an exception is thrown during memory allocation.

    ClickHouse has the "parseDateTimeBestEffort" function: https://clickhouse.com/docs/en/sql-reference/functions/type-... and here is its source code: https://github.com/ClickHouse/ClickHouse/blob/74d8551dadf735...