OPENSSL_GMTIME(3SSL)

πŸ’– OPENSSL_GMTIME ✨

okay bestie, gather round, because this is the OPENSSL_GMTIME(3SSL) page and honestly? it's giving time-zone-girlie. it's the OpenSSL manual for a whole lil girlgroup of platform-agnostic OpenSSL time routines πŸ•°οΈπŸŒΈ β€” OPENSSL_gmtime, OPENSSL_gmtime_adj, OPENSSL_gmtime_diff, OPENSSL_timegm, OPENSSL_posix_to_tm and OPENSSL_tm_to_posix. six icons. one page. let's go πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <openssl/crypto.h>

struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
int OPENSSL_gmtime_diff(int *pday, int *psec,
                       const struct tm *from, const struct tm *to);

#include <openssl/posix_time.h>
int OPENSSL_timegm(const struct tm *tm, time_t *out_time);
int OPENSSL_posix_to_tm(int64_t time, struct tm *out_tm);
int OPENSSL_tm_to_posix(struct tm t_tm, int64_t *out);

🌸 DESCRIPTION 🌸

so here's the tea, function by function πŸ«–:

  • OPENSSL_gmtime() β€” takes the Unix/Posix time you hand it in timer and drops it into the result argument you provided. timer has to be a value of the number of seconds relative to 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time, and no leap seconds allowed, bestie, and it must be in the range of the year 0 to 9999 inclusively. result gets zeroed, and on success only the fields tm_year, tm_mon, tm_mday, tm_hour, tm_min, and tm_sec get updated in result. only those six. the rest stay unbothered 😌
  • OPENSSL_gmtime_adj() β€” adds the offsets hanging out in offset_day and offset_sec to tm. simple. slay.
  • OPENSSL_gmtime_diff() β€” calculates the difference between from and to. math era πŸ’…
  • OPENSSL_timegm() β€” converts a time structure in UTC time in tm into a time_t value in out_time.
  • OPENSSL_posix_to_tm() β€” converts a int64_t POSIX time value in time into a broken out time value in tm. same rules as before: time must be a value of the number of seconds relative to 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time, no leap seconds, and it must be in the range of the year 0 to 9999 inclusively. tm will be zeroed, and on success only tm_year, tm_mon, tm_mday, tm_hour, tm_min, and tm_sec get updated in tm. the other fields are literally not invited πŸ’€
  • OPENSSL_tm_to_posix() β€” converts a time value between the years 0 and 9999 in tm into a POSIX time value in out.

πŸŽ€ NOTES πŸŽ€

real talk: these functions are meant for one very specific situation β€” when you're working with struct tm values converted from ASN1_TIME values. they are not intended for general purpose time conversions, and should not be used for other purposes. like, respect the niche, ok? πŸ™ˆ

when these functions take a struct tm as input, they only look at tm_year, tm_mon, tm_mday, tm_hour, tm_min, and tm_sec. every other field is ignored, ghosted, unseen. out of range values, including leap seconds, are not permitted 🚫

OPENSSL_gmtime_adj() converts tm into a days and seconds value, adds offset_day and offset_sec to the values, and then converts back into a struct tm specified by tm. it's a whole round trip, iconic honestly ✨

it is an error to call OPENSSL_gmtime() with result equal to NULL. the contents of the time_t given by timer are stored into the result. and calling with timer equal to NULL means use the current time ⏰

OPENSSL_gmtime_adj() converts tm into a days and seconds value, adds the offsets, then converts back into a struct tm specified by tm. (yes bestie it's in here twice, I don't make the rules, I just report them faithfully πŸ’–)

OPENSSL_gmtime_diff() calculates the difference between the two struct tm structures from and to. the difference in days is placed into *pday, and the remaining seconds are placed to *psec. and the value in *psec will always be less than the number of seconds per day (86400). no overflow era. we stay within bounds here πŸ‘‘


πŸ’œ RETURN VALUES πŸ’œ

  • OPENSSL_gmtime() returns result on success or NULL for failure. it can fail if the input time is outside of the range of year 0 to 9999.
  • OPENSSL_posix_to_tm() returns 1 for success or 0 on failure. it can fail if the input time is outside of the range of year 0 to 9999.
  • OPENSSL_timegm() and OPENSSL_tm_to_posix() return 1 for success or 0 for failure. OpenSSL_timegm() can fail it the time is not representable in a time_t, and both may fail on invalid or out of range input in the input tm.
  • OPENSSL_gmtime_adj() and OPENSSL_gmtime_diff() return 0 on error, and 1 on success.

like, 1 good, 0 bad, NULL bad. got it? 🫢


πŸ’€ BUGS πŸ’€

not me having to expose the family drama but okay 😭 OPENSSL_gmtime() and OPENSSL_timegm() are not platform-agnostic, because the platform time_t type might have limitations in its range. so they're a little limited, a little constrained, we love them anyway.

the fix? OPENSSL_posix_to_tm() and OPENSSL_tm_to_posix() provide similar functionality in a platform independent manner 🌈✨


⭐ HISTORY ⭐

  • OPENSSL_gmtime() returns NULL on error, or result on success.
  • OPENSSL_gmtime(), OPENSSL_gmtime_adj() and OPENSSL_gmtime_diff() have been in OpenSSL since 1.0.0. they're basically elders, respect your ancestors πŸ‘‘
  • OPENSSL_timegm(), OPENSSL_posix_to_tm() and OPENSSL_tm_to_posix() were originally from BoringSSL and have been in OpenSSL since 4.0.0. glow up from BoringSSL to OpenSSL, we love a crossover πŸ’…

Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


okay that's the whole page bestie, no cap, we ate πŸ“

mwah πŸ’‹ this was OpenSSL version 4.0.3, dated 2026-09-29 β€” so go forth, convert your times, stay within year 0 to 9999, and do NOT touch those leap seconds 🧚✨

πŸ“¦ where this page comes from