2017-08-11 133 views
0

我做了一個LED掛鐘&基於arduino a日曆,現在我想修改它添加一個變量來自動調整DST的偏移量。我已經每天輪詢互聯網時間服務器2x以確保準確性,但時間服務器通常不提供DST信息。變化發生在三月的第二個星期日和十一月的第一個星期日。 (https://www.nist.gov/pml/time-and-frequency-division/popular-links/daylight-saving-time-dst)本質上,我需要知道它是3月的第2個星期天,並告訴它將時區偏移量調整+1,然後在11月的第1個星期日上調整-1。我只是不知道如何實現這一點。如何計算當月的星期日?

我想喜歡的事:

如果 月== 3或11 和 如果平日== 1; 然後 星期日+ 1; else 星期日= 0;

if sunday == 2; AND month == 3; then isDST = TRUE;

if sunday == 1; AND month == 11; 然後 isDST = FALSE;

我希望這是我想做的事情的一個很好的例子。我討厭使用這麼多嵌套的if,但是這是我能想到的最好的,仍然是一個相對的新手。這甚至會起作用,還是有更好的方法去解決它?任何幫助,這將不勝感激。

+0

在電信領域的一些嵌入式系統,DST一直被認爲 '本地' 選項。因此,這些系統提供了用戶命令來啓用/禁用DST,每個設施/州/市的偏好。 –

+0

在電信系統中,用戶啓用(或不啓用)DST,並且DST設置更改了報告的時間顯示或時間,並更改了用戶提示和手動設置時鐘的指導。已經有一段時間了,所以我不確定,但我認爲時間自動更新(來自用戶指定的時間服務器)是DST沒有意義的事情。 –

+0

你有C++ 11嗎? –

回答

1

這是一個paper with calendrical algorithms,可以用來計算像3月第二個星期天那樣的事情。請參閱Example: Finding nth weekday of month

如果您有C++ 11可用,您可以使用此free, open-source date library以非常高級的語法來計算這樣的事情。該庫使用底層的the paper算法。例如:

std::chrono::system_clock::time_point 
DST_US(std::chrono::system_clock::time_point tp, std::chrono::hours std_offset) 
{ 
    using namespace date; 
    using namespace std::chrono; 
    const auto y = year_month_day{floor<days>(tp)}.year(); 
    const auto begin = sys_days{sun[2]/mar/y} + 2h - std_offset; // DT begins at this UTC time 
    const auto end = sys_days{sun[1]/nov/y} + 1h - std_offset; // ST begins at this UTC time 
    if (tp < begin || end <= tp) 
     return tp + std_offset; 
    return tp + std_offset + 1h; 
} 

隨意,如果你要使用datetime庫C++ 11(這是便攜式),並在the paper使用的算法,否則創建自己的。

免責聲明:時區規則始終在變化。上述對於自制時鐘來說當然是足夠的。對於需要最新時區規則的工業強度應用,請使用基於IANA timezone database的庫,如this one

0

在這裏,我爲你製作了一個C++代碼。你不需要C++ 11來運行它。

它是如何工作的,它得到當前的月份和年份。檢查年度是閏年,然後繼續並設置最大日數。假設2017年8月。最大日期爲31天。

如果它遇到的那一天是星期日,程序開始運行並計數sundayCounter

這樣就可以自動獲得當月的星期日數量。

這是我的代碼,請隨時使用它。它完全符合你想要做的。你想要的變量是sundayCounter。玩的開心。

#include <iostream> 
#include <ctime> 
using namespace std; 

int main() 
{ 
    bool isLeap = false; 
    int sundayCounter = 0; 
    int MAX_DAY; 
    int month, year; 
    string monthText; 

    time_t theTime = time(NULL); 
    struct tm *aTime = localtime(&theTime); 
    month = aTime->tm_mon; 
    year = aTime->tm_year; 

    if (year % 4 == 0) 
     {; 
      if (year % 100 == 0) 
      { 
       if (year % 400 == 0) 
        isLeap = true; 
       else 
        isLeap = false; 
      } 
      else 
       isLeap = true; 
     } 
    else { 
     isLeap = false; 
    } 

    switch(month) 
    { 
    case 0: 
     MAX_DAY = 31; 
     break; 
    case 1: 
     if(isLeap) 
      MAX_DAY = 29; 
     else 
      MAX_DAY = 28; 
     break; 
    case 2: 
     MAX_DAY = 31; 
     break; 
    case 3: 
     MAX_DAY = 30; 
     break; 
    case 4: 
     MAX_DAY = 31; 
     break; 
    case 5: 
     MAX_DAY = 30; 
     break; 
    case 6: 
     MAX_DAY = 31; 
     break; 
    case 7: 
     MAX_DAY = 31; 
     break; 
    case 8: 
     MAX_DAY = 30; 
     break; 
    case 9: 
     MAX_DAY = 31; 
     break; 
    case 10: 
     MAX_DAY = 30; 
     break; 
    case 11: 
     MAX_DAY = 31; 
     break; 
    } 

    for(int day = 0; day <= MAX_DAY; day++) { 
     struct tm time_in = { 0, 0, 0, // second, minute, hour 
       day, month + 1, year - 1900 }; // 1-based day, 0-based month, year since 1900 

     time_t time_temp = mktime(& time_in); 

     // the return value from localtime is a static global - do not call 
     // this function from more than one thread! 
     tm const *time_out = localtime(& time_temp); 

     switch(time_out->tm_wday) 
     { 
     case 0: 
      sundayCounter++; 
      break; 
     } 
    } 

    const char* month_list[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; 
    int current_month = month+1; 
    const char* current_month_name = month_list[current_month-1]; 
    cout << "Sunday amount in " << current_month_name << " " << (year + 1900) << ": " << sundayCounter; 
    cout << endl; 
    return 0; 
} 

輸出:

Sunday amount in August 2017: 4