I didn't find a trivial way to get the time offset in minutes between the local time and the UTC time.
At first I intended to use tzset()
but it doesn't provide the daylight saving time. According to the man page, it is simply an integer different of zero if day light saving is in effect. While it is usually an hour, it may be half an hour in some country.
I would prefer avoiding to compute the time difference between current UTC returned by gmtime()
and localtime()
.
A more general solution would give me this information for a specified location and a positive time_t value, or at least locally.
Edit 1: the use case is to get the right local time offset for https://github.com/chmike/timez. BTW, If you thought libc functions to manipulate time were Ok, read this https://rachelbythebay.com/w/2013/03/17/time/.
Edit 2: the best and simplest solution I have so far to compute the time offset to UTC in minutes is
// Bogus: assumes DST is always one hour
tzset();
int offset = (int)(-timezone / 60 + (daylight ? 60 : 0));
The problem is to determine the real day light saving time.
Edit 3: Inspired by the answer of @trenki, I came up with the following solution. This is a hack in that it tricks mktime()
to consider the output of gmtime()
as the localtime. The result is inaccurate when the DST change is in the time span between UTC time and localtime.
#include <stdio.h>
#include <time.h>
int main()
{
time_t rawtime = time(NULL);
struct tm *ptm = gmtime(&rawtime);
// Request that mktime() looksup dst in timezone database
ptm->tm_isdst = -1;
time_t gmt = mktime(ptm);
double offset = difftime(rawtime, gmt) / 60;
printf("%f\n", offset);
return 0;
}
(GMT-5:00) Eastern Time (US & Canada) Add the local time offset to the UTC time. For example, if your local time offset is -5:00, and if the UTC time is shown as 11:00, add -5 to 11. The time setting when adjusted for offset is 06:00 (6:00 A.M.). Note The date also follows UTC format.
Definition and Usage. getTimezoneOffset() returns the difference between UTC time and local time. getTimezoneOffset() returns the difference in minutes. For example, if your time zone is GMT+2, -120 will be returned.
A UTC offset is the difference in hours and minutes between a particular time zone and UTC, the time at zero degrees longitude. For example, New York is UTC-05:00, which means it is five hours behind London, which is UTC±00:00.
Here is my way:
time_t z = 0;
struct tm * pdt = gmtime(&z);
time_t tzlag = mktime(pdt);
Alternative with automatic, local storage of struct tm
:
struct tm dt;
memset(&dt, 0, sizeof(struct tm));
dt.tm_mday=1; dt.tm_year=70;
time_t tzlag = mktime(&dt);
tzlag
, in seconds, will be the negative of the UTC offset; lag of your timezone Standard Time compared to UTC:
LocalST + tzlag = UTC
If you want to also account for "Daylight savings", subtract tm_isdst
from tzlag
, where tm_isdst
is the field for a particular local time struct tm
, after applying mktime
to it (or after obtaining it with localtime
).
Why it works:
The set struct tm
is for "epoch" moment, Jan 1 1970, which corresponds to a time_t
of 0.
Calling mktime()
on that date converts it to time_t
as if it were UTC (thus getting 0), then subtracts the UTC offset from it in order to produce the output time_t
. Thus it produces negative of UTC_offset.
Does your system's strftime() function support the %z
and %Z
specifiers? On FreeBSD,
%Z is replaced by the time zone name. %z is replaced by the time zone offset from UTC; a leading plus sign stands for east of UTC, a minus sign for west of UTC, hours and minutes follow with two digits each and no delimiter between them (common form for RFC 822 date headers).
and I can use this to print this:
$ date +"%Z: %z"
CEST: +0200
ISO C99 has this in 7.23.3.5 The strftime
function:
%z is replaced by the offset from UTC in the ISO 8601 format ‘‘−0430’’ (meaning 4 hours 30 minutes behind UTC, west of Greenwich), or by no characters if no time zone is determinable. [tm_isdst] %Z is replaced by the locale’s time zone name or abbreviation, or by no characters if no time zone is determinable. [tm_isdst]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With