Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 确定DST是否在给定时间的指定时区有效_C_Timezone_Dst - Fatal编程技术网

C 确定DST是否在给定时间的指定时区有效

C 确定DST是否在给定时间的指定时区有效,c,timezone,dst,C,Timezone,Dst,我如何确定夏令时是否在指定的时区有效,只要给定时间?我知道“在POSIX系统中,用户可以通过TZ环境变量指定时区。”我想我可以保存当前TZ值(如果设置),将其更改为我感兴趣的TZ,调用localtime()并选中tm_isdst,然后将TZ更改回其原始值。我只是不确定它的便携性 有没有一种便携式方法来确定时区的DST(给定C语言中的时间)?这是我所能做到的便携式方法。我对任何更好的解决方案都感兴趣。我所做的是计算给定年份美国/纽约时区从epoch到DST开始和结束的时间,并测试给定的时间是否介于

我如何确定夏令时是否在指定的时区有效,只要给定
时间
?我知道“在POSIX系统中,用户可以通过TZ环境变量指定时区。”我想我可以保存当前TZ值(如果设置),将其更改为我感兴趣的TZ,调用
localtime()
并选中
tm_isdst
,然后将TZ更改回其原始值。我只是不确定它的便携性


有没有一种便携式方法来确定时区的DST(给定C语言中的
时间)

这是我所能做到的便携式方法。我对任何更好的解决方案都感兴趣。我所做的是计算给定年份美国/纽约时区从epoch到DST开始和结束的时间,并测试给定的
时间是否介于两者之间。这是特定于美国/纽约时区的,但我可以想象,经过一些努力,它可以很容易地适应另一个时区,或适应任何/所有时区

如果使用GNU C库,
timegm
可以用来代替
getenv
mktime
setenv
,但根据以下条件:

mktime
基本上是通用的
timegm
相当罕见。 用于从UTC故障时间到 简单时间,将
TZ
环境变量设置为
UTC
,调用
mktime
,然后 将
TZ
设置回原位

#包括
#包括
#包括
#包括
/***********************************************\
*在美国/纽约:
*DST开始:3月的第二个星期日当地时间02:00,之后EDT==UTC-04:00
*DST结束:11月的第一个星期日当地时间02:00,之后EST==UTC-05:00
\***********************************************/
//如果UTC的年份大于美国/纽约的年份,则返回1
//给定的时间t。换句话说,在时间t,是在UTC的00:00:00之间吗
//(午夜)1月1日和UTC 1月1日05:00:00。如果UTC所在年份为
//与美国/纽约时间t相同。
int UTCYEARIS更大(时间\时间){
时间不是开始,而是结束;
struct tm*tm;
tm=gmtime(时间和时间);
如果(tm->tm\u mon==11&&tm->tm\u mday==31&&
(tm->tm_小时>=19&&tm->tm_小时<5)){
返回1;
}
返回0;
}
//返回从epoch到美国/纽约DST开始的秒数,即3月的第二个星期日(ssim)。
//对于给定的年份。
时间(整数年){
时间t,t2;
int-sim=0;
struct tm={0};
tm.tm_年=年;
tm.tm_mon=2;
tm.tmmday=1;
tm.tm_小时=7;
char*env;
env=getenv(“TZ”);
setenv(“TZ”,“UTC”,1);
t=mktime(&tm);
tm=*gmtime(&t);
而(sim<2){
如果(tm.tm_wday==0){
sim+=1;
如果(sim==2){break;}
}
tm.tm_mday+=1;
tm.tm_wday=0;
t=mktime(&tm);
tm=*gmtime(&t);
}
t=mktime(&tm);
if(env==NULL){
未清算的环境(“TZ”);
}否则{
setenv(“TZ”,环境,1);
}
返回t;
}
//返回从epoch到DST在美国/纽约结束的秒数,即11月的第一个星期日(fsin)。
//对于给定的年份。
时间单位(整数年){
时间;
struct tm={0};
tm.tm_年=年;
tm.tm_mon=10;
tm.tmmday=1;
tm.tm_小时=6;
char*env;
env=getenv(“TZ”);
setenv(“TZ”,“UTC”,1);
t=mktime(&tm);
tm=*gmtime(&t);
而(1){
如果(tm.tm_wday==0){break;}
tm.tm_mday+=1;
tm.tm_wday=0;
t=mktime(&tm);
tm=*gmtime(&t);
}
t=mktime(&tm);
if(env==NULL){
未清算的环境(“TZ”);
}否则{
setenv(“TZ”,环境,1);
}
返回t;
}
//如果DST在时间t在美国/纽约生效,则返回1,否则返回0
int DSTINYC(时间){
时间开始,结束;
struct tm*tm_ptr;
tm_ptr=gmtime(&t);
如果(UTCYEAR大于(t)){
tm_ptr->tm_year-=1;
}
beginDST=ssim(tm_ptr->tm_年);
endDST=fsin(tm_ptr->tm_年);
返回(t>=beginDST&t
“可移植方式”->不,高度可移植(在POSIX中)-->可能。由于post没有标记[POSIX],不清楚您是在寻求POSIX答案还是便携式(标准C)答案。我可以问一下,为什么您想知道DST是否有效?您是否正计划显示类似“嘿,用户,您知道DST现在生效了吗?”之类的内容,或者这是您正在尝试的更复杂内容中的一部分?通常当我问这个问题时,答案是后者,解决方案是使用一个库,如或HHinnet的and库。@chux如果可能的话,我正在寻找可移植的。到目前为止,代码将在POSIX环境中运行,但谁知道未来会发生什么。@MattJohnson我想在特定时间(东部/美国)执行操作,但代码将在不同的时区中运行。我将研究这些库。不要在代码中写入任何依赖于代码运行时区的内容,除非您实际上打算暗示“本地时间”,例如在设备上向用户显示的时钟中。在服务器端代码和许多其他情况下,只需从机器上获取UTC时间,并处理时区转换
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

/***********************************************\
 * In America/New_York:
 * DST begins: second Sunday in March 02:00 local, after which EDT == UTC-04:00
 * DST ends: first  Sunday in November 02:00 local, after which EST == UTC-05:00
\***********************************************/

//Return 1 if the year at UTC is greater than the year in America/New_York at
//the given time t.  In other words, at time t, is it between 00:00:00 UTC 
//(midnight) Jan 1 and 05:00:00 UTC Jan 1.  Return 0 if the year at UTC is the 
//same as America/New_York at time t.
int UTCyearIsGreater(time_t when) {
    time_t begin, end;
    struct tm* tm;
    tm = gmtime(&when);
    if (tm->tm_mon == 11 && tm->tm_mday == 31 &&
            (tm->tm_hour >= 19 && tm->tm_hour < 5)) {
        return 1;
    }
    return 0;
}

//Return number of seconds from epoch until DST begins/began in America/New_York, the second Sunday in March (ssim).
//for the given year.
time_t ssim(int year) {
    time_t t, t2;
    int sim = 0;
    struct tm tm = {0};
    tm.tm_year = year;
    tm.tm_mon = 2;
    tm.tm_mday = 1;
    tm.tm_hour = 7;
    char* env;
    env = getenv("TZ");
    setenv("TZ", "UTC", 1);
    t = mktime(&tm);
    tm = *gmtime(&t);
    while (sim < 2) {
        if (tm.tm_wday == 0) {
            sim += 1;
            if (sim == 2) { break; }
        }
        tm.tm_mday += 1;
        tm.tm_wday = 0;
        t = mktime(&tm);
        tm = *gmtime(&t);
    }
    t = mktime(&tm);
    if (env == NULL) {
        unsetenv("TZ");
    } else {
        setenv("TZ", env, 1);
    }
    return t;
}

//Return number of seconds from epoch until DST ends/ended in America/New_York, the first Sunday in November (fsin).
//for the given year.
time_t fsin(int year) {
    time_t t;
    struct tm tm = {0};
    tm.tm_year = year;
    tm.tm_mon = 10;
    tm.tm_mday = 1;
    tm.tm_hour = 6;
    char* env;
    env = getenv("TZ");
    setenv("TZ", "UTC", 1);
    t = mktime(&tm);
    tm = *gmtime(&t);
    while (1) {
        if (tm.tm_wday == 0) { break; }
        tm.tm_mday += 1;
        tm.tm_wday = 0;
        t = mktime(&tm);
        tm = *gmtime(&t);
    }
    t = mktime(&tm);
    if (env == NULL) {
        unsetenv("TZ");
    } else {
        setenv("TZ", env, 1);
    }
    return t;
}

//Return 1 if DST is in effect in America/New_York at time t, return 0 otherwise
int DSTinNYC(time_t t) {
    time_t beginDST, endDST;
    struct tm* tm_ptr;
    tm_ptr = gmtime(&t);
    if (UTCyearIsGreater(t)) {
        tm_ptr->tm_year -= 1;
    }
    beginDST = ssim(tm_ptr->tm_year);
    endDST = fsin(tm_ptr->tm_year);
    return (t >= beginDST && t < endDST);
}

int main() {
    //test it
    if (DSTinNYC(1461179392)) { 
        printf("CORRECT 20 Apr 2016 15:09:52 EDT\n");
    } else {
        printf("FAILED 20 Apr 2016 15:09:52 EDT\n");
    }
    if (DSTinNYC(1455993975)) { 
        printf("FAILED 20 Feb 2016 13:46:15 EST\n");
    } else {
        printf("CORRECT 20 Feb 2016 13:46:15 EST\n");
    }
    if (DSTinNYC(1571179392)) { 
        printf("CORRECT 15 Oct 2019 18:43:12 EDT\n");
    } else {
        printf("FAILED 15 Oct 2019 18:43:12 EDT\n");
    }
    //results checked with http://www.epochconverter.com/
    return 0;
}