The usual way of answering this question makes use of the comprehensive tz database , which is built into most operating systems, with the exception of Windows, which uses its own, similar database. A database like this is necessary in order for the C library localtime and mktime functions to work correctly. If you already have a broken-down date and time (year/month/day, hour:minute:second), the function you want is mktime . Let's try two dates, July 8th and December 13th.
at 12:00:00 on 2022-07-08, DST was in effect
at 12:00:00 on 2022-12-13, DST was not in effect
When filling in struct tm , there are a couple of things to be careful of, as illustrated in the code above:
field tm_year is offset by 1900
field tm_mon is offset by 1 (it's 0-based)
field tm_isdst contains 1 if DST is in effect, 0 if its not, or -1 if we're not sure.
So the strategy is simply: fill in a struct tm with the desired date/time, set tm_isdst to -1 indicating that we don't know whether DST is in effect or not, and call mktime . Among other things, mktime figures out whether DST was in effect or not, and adjusts tm_isdst in the pointed-to struct tm accordingly. If the "UTC timestamp" you said you had to start with is a Unix-style time_t value, you can answer your question using the localtime function, which starts with a time_t value and constructs a struct tm :
time_t t = 1670714400;
struct tm *tmp = localtime(&t);
printf("at %d:%02d:%02d on %d-%02d-%02d, DST %s in effect\n",
tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
tmp->tm_year+1900, tmp->tm_mon+1, tmp->tm_mday,
tmp->tm_isdst ? "was" : "was not");
On my machine this prints
at 18:20:00 on 2022-12-10, DST was not in effect
I've glossed over one important question, which is: how do localtime and mktime know which of the world's time zone and daylight savings rules to use? For Unix-like operating systems, at least, it's based on an environment variable, TZ . Normally it's set to match the part of the world where you are (where your computer is installed), although you can set it to anything you want. For example, if I wanted my program to use the rules for Central European time, I'd set TZ to Europe/Rome , the tz identifier for that zone. The usual way of setting environment variables (again, under Unix) is from the shell, outside of your C program. For example, to run my program under a different time zone, I might type
TZ=Europe/Rome
export TZ
./myprogram
Or there's this shortcut:
TZ=Europe/Rome ./myprogram
Or, you can also set an environment variable from within a C program, like this:
setenv("TZ", "Europe/Rome", 1);
tzset();
setenv is a Posix function, not Standard C. After you change the TZ environment variable from within a C program like this, you have to call tzset to let the timezone-related functions like mktime know you've done so.
#include <stdio.h>
#include <stdlib.h>
//included for reference only
int wd(int y, int m, int d)
{
return (d += m<3?y--:y-2, 23*m/9 + d+4 + y/4 - y/100 + y/400) % 7;
//https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Keith
}
#define GregorianAdpotion 1752
int main(int argc, char *argv[])
{
int y = argc > 1 ? atoi(argv[1]) : 2022;
if (y <= GregorianAdpotion)
return 1;
//https://rosettacode.org/wiki/Find_the_last_Sunday_of_each_month#FreeBASIC
int x = 33+y + y/4 - y/100 + y/400; //common part of Keith for Mar and Oct
int last_Sun_March = 31 - x % 7;
int last_Sun_Oct = 31 - (4 + x) % 7;
printf("DST from %d-03-%d 02:00 CET ", y, last_Sun_March);
printf("to %d-10-%d 03:00 CEST\n", y, last_Sun_Oct);
return 0;
}
2条答案
按热度按时间qnzebej01#
The usual way of answering this question makes use of the comprehensive tz database , which is built into most operating systems, with the exception of Windows, which uses its own, similar database.
A database like this is necessary in order for the C library
localtime
andmktime
functions to work correctly.If you already have a broken-down date and time (year/month/day, hour:minute:second), the function you want is
mktime
. Let's try two dates, July 8th and December 13th.For me this prints
When filling in
struct tm
, there are a couple of things to be careful of, as illustrated in the code above:tm_year
is offset by 1900tm_mon
is offset by 1 (it's 0-based)tm_isdst
contains 1 if DST is in effect, 0 if its not, or -1 if we're not sure.So the strategy is simply: fill in a
struct tm
with the desired date/time, settm_isdst
to -1 indicating that we don't know whether DST is in effect or not, and callmktime
. Among other things,mktime
figures out whether DST was in effect or not, and adjuststm_isdst
in the pointed-tostruct tm
accordingly.If the "UTC timestamp" you said you had to start with is a Unix-style
time_t
value, you can answer your question using thelocaltime
function, which starts with atime_t
value and constructs astruct tm
:On my machine this prints
I've glossed over one important question, which is: how do
localtime
andmktime
know which of the world's time zone and daylight savings rules to use? For Unix-like operating systems, at least, it's based on an environment variable,TZ
. Normally it's set to match the part of the world where you are (where your computer is installed), although you can set it to anything you want. For example, if I wanted my program to use the rules for Central European time, I'd set TZ toEurope/Rome
, the tz identifier for that zone.The usual way of setting environment variables (again, under Unix) is from the shell, outside of your C program. For example, to run my program under a different time zone, I might type
Or there's this shortcut:
Or, you can also set an environment variable from within a C program, like this:
setenv
is a Posix function, not Standard C. After you change theTZ
environment variable from within a C program like this, you have to calltzset
to let the timezone-related functions likemktime
know you've done so.yfwxisqw2#
夏令时从三月的最后一个星期日(02:00 CET)到十月的最后一个星期日(03:00 CEST)。(https://en.wikipedia.org/wiki/Summer_time_in_Europe)。要进行测试,请与https://www.timeanddate.com/time/change/germany?year=2022进行比较,例如