c
  • datetime
  • time
  • timezone
  • 2010-03-09 34 views 6 likes 
    6

    的信息頁的GNU date命令包含這個例子:如何以編程方式將時間從一個時區轉換爲另一個時區?

    例如,與GNU date 命令,你可以回答這個問題 「現在是什麼時候在紐約當 巴黎時鐘顯示6 :10月30日上午 31,2004?通過使用開始 用`TZ =「歐洲/巴黎」日期「作爲 顯示下面的shell成績單:

    $ export TZ="America/New_York" 
    $ date --date='TZ="Europe/Paris" 2004-10-31 06:30' 
    Sun Oct 31 01:30:00 EDT 2004 
    

    在這個例子中,‘--date’ 操作數以自己的」 TZ ' 設置,因此該操作數 的其餘部分根據 「歐洲/巴黎」規則進行處理,將 字符串2004-10-31 06:30當作 在巴黎處理。但是,由於date命令的 輸出是 根據整體 時區規則進行處理,因此它使用紐約 時間。 (巴黎是正常6小時 比紐約早在2004年,但這個 例子是指一個簡短的萬聖節 時期的差距是五小時)。

    我想編程基本上完成同樣的事情在C而無需撥打date程序數百萬次。基本上我正在尋找一種方法在一個時區採取任意日期和時間,並將其轉換爲另一個時區中的等效日期和時間,直接或通過UTC和UTC的轉換。只要我可以使用標準功能(strftime/strptime/mktime/etc)來操作它們,我不關心輸入和輸出時間的格式。

    date程序似乎做到這一點使用內部的coreutils封裝複雜的程序,我正在尋找一種方式使用標準POSIX/Linux的程序或外部庫做這在C。我看了一下zoneinfo,這似乎很有前途,但我找不到任何圖書館來做任何有用的工作。

    回答

    2

    對於時間:

    • 獲取GMT時間gmtime
    • 添加/ time_t.tm_hour
    • 使用mktime減去小時來重新規格化

    日期計算將類似於但更復雜一點。

    +1

    有一些微妙的問題涉及手動計算,我試圖避免,如必須處理如DST。這些信息包含在zoneinfo數據庫中,但目前尚未證實對我有用。 – 2010-03-09 23:49:33

    +1

    例如,這項工作在委內瑞拉尤其糟糕 - 這是正式的UTC-4:30 – Quintus 2010-03-10 00:30:41

    3

    我想出了一個解決方案,似乎在使用glibc的Linux上工作,我不知道這種行爲是如何可移植的,任何關於可移植性或更好的方式去評論這個行爲的意見都是值得歡迎的。

    convert_time。C(無錯誤爲了清楚檢查):

    #define _XOPEN_SOURCE 
    #include <time.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    
    int main (int argc, char *argv[]) 
    { 
        struct tm mytm = {0}; 
        time_t mytime; 
        char buf[100]; 
    
        mytm.tm_isdst = -1; 
        putenv(argv[1]); 
        tzset(); 
        strptime(argv[2], "%Y-%m-%d %H:%M", &mytm); 
        mytime = mktime(&mytm); 
    
        putenv(argv[3]); 
        tzset(); 
        localtime_r(&mytime, &mytm); 
        strftime(buf, 100, "%a, %d %b %Y %H:%M:%S %z(%Z)", &mytm); 
        puts(buf); 
    
        return 0; 
    } 
    

    第一個參數是所述源時區(實際上是「TZ =時區」傳遞給運行putenv),第二個參數是指定格式時,最後一個參數是目的地時區。我正在使用glibc支持使用zoneinfo數據庫的zoneinfo時區名稱。

    的幾個DST測試角案件的結果對應的結果從相當於date命令以及this網站,它使用的時區信息數據庫:

    $ ./convert_time "TZ=America/New_York" "2005-05-31 06:30" "TZ=America/Indiana/Indianapolis" 
    Tue, 31 May 2005 05:30:00 -0500(EST) 
    
    $ ./convert_time "TZ=America/New_York" "2006-05-31 06:30" "TZ=America/Indiana/Indianapolis" 
    Wed, 31 May 2006 06:30:00 -0400(EDT) 
    
    $ ./convert_time "TZ=Europe/Paris" "2004-10-30 06:30" "TZ=America/New_York" 
    Sat, 30 Oct 2004 00:30:00 -0400(EDT) 
    
    $ ./convert_time "TZ=Europe/Paris" "2004-10-31 06:30" "TZ=America/New_York" 
    Sun, 31 Oct 2004 01:30:00 -0400(EDT) 
    
    $ ./convert_time "TZ=Europe/Paris" "2004-11-01 06:30" "TZ=America/New_York" 
    Mon, 01 Nov 2004 00:30:00 -0500(EST) 
    
    +1

    Yuck,但你能做什麼?這正是man page所要做的:http://www.kernel.org/doc/man-pages/online/pages/man3/timegm.3.html。這只是可怕的線程不安全。 – smparkes 2011-11-01 23:48:49

    0

    實際上,我是找你做了同樣的答案,這是我想出的解決方案。 以下示例程序將獲取本地系統時間並將其轉換爲所需的任何時區。

    // compile: gcc snippet.c 
    // usage: ./a.out Europe/Berlin Pacific/Nauru Asia/Hong_Kong Asia/Kabul 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <time.h> 
    #include <errno.h> 
    
    int main(int argc, char *argv[]) 
    { 
         char buf[80]; 
         time_t tt = time(NULL); 
         struct tm tm; 
         int i; 
    
         if (!localtime_r(&tt, &tm)) { 
           printf("Could not convert time_t to tm struct. %s\n", strerror(errno)); 
           return 1; 
         } 
    
         printf("time_t: %ld\n", tt); 
         printf("timezone: %ld, %s/%s, daylight:%d\n", timezone, tzname[0], tzname[1], daylight); 
         strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z %Z", &tm); 
         printf("time: %s\n", buf); 
    
         for (i = 1; i < argc; ++i) { 
           printf("\ninput: %s\n", argv[i]); 
    
           snprintf(buf, sizeof(buf), "TZ=%s", argv[i]); 
           putenv(buf); 
           tzset(); 
           printf("\ttimezone: %ld, %s/%s, daylight:%d\n", timezone, tzname[0], tzname[1], daylight); 
    
           if (!localtime_r(&tt, &tm)) { 
             printf("Could not convert time_t to tm struct. %s\n", strerror(errno)); 
             return 1; 
           } 
    
           strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z %Z", &tm); 
           printf("\ttime: %s\n", buf); 
         } 
    
         return 0; 
    } 
    
    相關問題