Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.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++ 如何确定下一次时钟何时调整为夏令时?_C++_C_Windows_Winapi_Dst - Fatal编程技术网

C++ 如何确定下一次时钟何时调整为夏令时?

C++ 如何确定下一次时钟何时调整为夏令时?,c++,c,windows,winapi,dst,C++,C,Windows,Winapi,Dst,我很好奇,是否有任何方法可以确定下一次夏令时调整的UTC日期/时间 类似于Windows报告的内容(请参见圆圈): 我认为没有专门针对这一点的API。我只需要从(C++)或(C)使用localtime(可能还有time和mktime)进行二进制搜索 一种基本方法是一次向前扫描三个月,直到返回的数据结构中的tm_isdst标志被翻转。然后,您可以在最后两个日期之间开始二进制搜索,以准确确定它何时翻转 有关参考资料,请参阅。此信息在Windows中由EnumDynamicTimeZoneInform

我很好奇,是否有任何方法可以确定下一次夏令时调整的UTC日期/时间

类似于Windows报告的内容(请参见圆圈):


我认为没有专门针对这一点的API。我只需要从
(C++)或
(C)使用
localtime
(可能还有
time
mktime
)进行二进制搜索

一种基本方法是一次向前扫描三个月,直到返回的数据结构中的
tm_isdst
标志被翻转。然后,您可以在最后两个日期之间开始二进制搜索,以准确确定它何时翻转


有关参考资料,请参阅。

此信息在Windows中由EnumDynamicTimeZoneInformation函数提供


请参见

有一个包含代码和数据的数据库:

非常感谢您的回复。而且,是的,事实上,我问的是Windows的WinAPI

我做了更多的研究,并提出了以下方法来满足我的需求。它使用C++和MFC的 CordEdTime<代码>,方便日期/时间计算。除此之外,它只是C++和WinAPIs。请检查我是否正确理解了
动态时区信息的文档。代码如下:

int GetNextDaylightSavingAdjustmentTime(SYSTEMTIME* pOutDtNextDST_Local, int* pnOutAdjustmentMin)
{
    //Get next time when DST adjustment will take place
    //'pOutDtNextDST_Local' = if not NULL, receives the (local) time when next DST adjustment will take place
    //'pnOutAdjustmentMin' = if not NULL, receives the amount of adjustment in minutes
    //RETURN:
    //      = 1 if got the time, or
    //      = 0 if DST is not used
    //      = -1 if error (check GetLastError() for info)
    int nOSError = NO_ERROR;

    //Load API dynamically (in case of Windows XP)
    BOOL (WINAPI *pfnGetDynamicTimeZoneInformation)(PDYNAMIC_TIME_ZONE_INFORMATION);
    (FARPROC&)pfnGetDynamicTimeZoneInformation =
        ::GetProcAddress(::GetModuleHandle(L"Kernel32.dll"), "GetDynamicTimeZoneInformation");

    DWORD tzID;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
    int nBiasDaylight;

    //Use newer API if possible
    if(pfnGetDynamicTimeZoneInformation)
    {
        DYNAMIC_TIME_ZONE_INFORMATION dtzi = {0};
        tzID = pfnGetDynamicTimeZoneInformation(&dtzi);

        StandardDate = dtzi.StandardDate;
        DaylightDate = dtzi.DaylightDate;

        nBiasDaylight = dtzi.DaylightBias;
    }
    else
    {
        //Older API
        TIME_ZONE_INFORMATION tzi = {0};
        tzID = GetTimeZoneInformation(&tzi);

        StandardDate = tzi.StandardDate;
        DaylightDate = tzi.DaylightDate;

        nBiasDaylight = tzi.DaylightBias;
    }

    int nRes = -1;
    int nAdjMins = 0;
    SYSTEMTIME stDstChange;
    memset(&stDstChange, 0, sizeof(stDstChange));

    SYSTEMTIME stDst;
    if(tzID == TIME_ZONE_ID_STANDARD ||
        tzID == TIME_ZONE_ID_DAYLIGHT)
    {
        stDst = tzID != TIME_ZONE_ID_DAYLIGHT ? DaylightDate : StandardDate;

        if(stDst.wMonth >= 1 &&
            stDst.wMonth <= 12 &&
            stDst.wDay >= 1 &&
            stDst.wDayOfWeek >= 0 &&
            stDst.wDayOfWeek <= 6)
        {
            //Get adjustment bias
            nAdjMins = tzID != TIME_ZONE_ID_DAYLIGHT ? -nBiasDaylight : nBiasDaylight;

            if(stDst.wYear == 0)
            {
                //Relative date

                SYSTEMTIME stLocal;
                ::GetLocalTime(&stLocal);

                //Begin from the 1st day of the month &
                //make sure that the date is in the future
                COleDateTime dt;
                for(int nYear = stLocal.wYear;; nYear++)
                {
                    dt.SetDateTime(nYear, stDst.wMonth, 1, stDst.wHour, stDst.wMinute, stDst.wSecond);
                    if(dt > COleDateTime::GetCurrentTime())
                        break;
                }

                int nRequiredWeek = stDst.wDay >= 1 && stDst.wDay <= 5 ? stDst.wDay : 5;

                for(int nCntDOW = 1;;)
                {
                    //0=Sunday, 1=Monday; 2=Tuesday; 3=Wednesday; 4=Thursday; 5=Friday; 6=Saturday
                    int dow = dt.GetDayOfWeek() - 1;
                    ASSERT(dow >= 0 && dow <= 6);

                    if(dow == stDst.wDayOfWeek)
                    {
                        if(nCntDOW >= nRequiredWeek)
                        {
                            //Stop
                            break;
                        }
                        else
                        {
                            nCntDOW++;
                        }
                    }

                    //Go to next day
                    dt += COleDateTimeSpan(1, 0, 0, 0);
                }

                //Convert back to system time
                if(dt.GetAsSystemTime(stDstChange))
                {
                    //Success
                    nRes = 1;
                }
                else
                {
                    //Failed
                    nOSError = ERROR_INVALID_FUNCTION;
                    ASSERT(NULL);
                }
            }
            else
            {
                //Absolute date
                stDstChange = stDst;

                nRes = 1;
            }
        }
        else
        {
            //Failed
            nOSError = ERROR_INVALID_PARAMETER;
            ASSERT(NULL);
        }
    }
    else
    {
        //DST is not used
        if(tzID == TIME_ZONE_ID_UNKNOWN)
        {
            nRes = 0;
        }
        else
        {
            //Error
            nOSError = ERROR_INVALID_DATA;
            ASSERT(NULL);
        }
    }


    if(pOutDtNextDST_Local)
        *pOutDtNextDST_Local = stDstChange;
    if(pnOutAdjustmentMin)
        *pnOutAdjustmentMin = nAdjMins;

    ::SetLastError(nOSError);
    return nRes;
}
int GetNextDaylightSavingAdjustmentTime(系统时间*pOutDtNextDST_本地,int*pnOutAdjustmentMin)
{
//获取下一次DST调整的时间
//“pOutDtNextDST_Local”=如果不为空,则接收下一次DST调整的(本地)时间
//“pnOutAdjustmentMin”=如果不为空,则以分钟为单位接收调整量
//返回:
//=1,如果有时间,或
//如果未使用DST,则=0
//=-1如果出现错误(请检查GetLastError()以获取信息)
int nOSError=无错误;
//动态加载API(对于Windows XP)
BOOL(WINAPI*pfnGetDynamicTimeZoneInformation)(PDYNAMIC\u TIME\u ZONE\u INFORMATION);
(FARPROC&)PFNGETDynamic时区信息=
::GetProcAddress(::GetModuleHandle(L“Kernel32.dll”),“GetDynamicTimeZoneInformation”);
德沃德·齐德;
系统时间标准日期;
SYSTEMTIME DaylightDate;
国际日光;
//如果可能,请使用更新的API
if(PFNGETDynamic时区信息)
{
动态时区信息dtzi={0};
tzID=pfnGetDynamicTimeZoneInformation(&dtzi);
StandardDate=dtzi.StandardDate;
DaylightDate=dtzi.DaylightDate;
nBiasDaylight=dtzi.DaylightBias;
}
其他的
{
//旧API
时区信息tzi={0};
tzID=获取时区信息(&tzi);
StandardDate=tzi.StandardDate;
DaylightDate=tzi.DaylightDate;
nBiasDaylight=tzi.日光偏差;
}
int nRes=-1;
int-nAdjMins=0;
系统时间变化;
memset(&stDstChange,0,sizeof(stDstChange));
系统时间标准测试;
如果(tzID==时区ID标准||
tzID==时区ID日光)
{
stDst=tzID!=时区\u ID\u日光?日光日期:标准日期;
如果(stDst.wMonth>=1&&
stDst.wMonth=1&&
stDst.wDayOfWeek>=0&&
stDst.wDayOfWeek COleDateTime::GetCurrentTime())
打破
}
int nRequiredWeek=stDst.wDay>=1&&stDst.wDay=0&&dow=nRequiredWeek)
{
//停止
打破
}
其他的
{
nCntDOW++;
}
}
//第二天去
dt+=COleDateTimeSpan(1,0,0,0);
}
//转换回系统时间
if(dt.GetAsSystemTime(stDstChange))
{
//成功
nRes=1;
}
其他的
{
//失败
nOSError=错误\无效\函数;
断言(空);
}
}
其他的
{
//绝对日期
stDstChange=stDst;
nRes=1;
}
}
其他的
{
//失败
nOSError=错误\无效\参数;
断言(空);
}
}
其他的
{
//未使用DST
如果(tzID==时区ID未知)
{
nRes=0;
}
其他的
{
//错误
nOSError=错误\无效\数据;
断言(空);
}
}
如果(pOutDtNextDST_本地)
*pOutDtNextDST_Local=标准变化;
如果(pnOutAdjustmentMin)
*pnOutAdjustmentMin=nAdjMins;
::SetLastError(NoError);
返回nRes;
}

另外,请记下我对
UTC
时间的请求。据我所知,在这种情况下更容易处理当地时间。

可能重复一个迂腐的注释:2014年11月2日1:59:59后的第二个夏令时是2014年11月2日1:00:00标准时间。2014年11月2日凌晨2:00夏令时不存在。看看那些根本不使用DST的国家,我想一个合理的限制应该是在当地时间一年后停止。@SirDarius是的,一年可能就可以了。我不认为C r/t答案适合Winapi问题,是吗?@david.pfx我没有注意到Winapi标签,并且假设需要一个更通用的解决方案(仅以Windows对话框为例)。我也不知道您在回答中引用的API调用。我感谢您的回答。它实际上让我了解了我在下面的代码中使用的
GetDynamicTimeZoneInformation
API或
GetTimeZoneInformation
。虽然很晚了,但因为这个回答对您有效(Q+A样式)应标记为