代码之家  ›  专栏  ›  技术社区  ›  tfinniga

将字符串从\日期\转换为时间\t

  •  11
  • tfinniga  · 技术社区  · 16 年前

    我正在尝试转换从 __DATE__ 宏入A time_t . 我不需要一个完整的日期/时间分析器,它只处理 第二代 宏将是伟大的。

    预处理器方法很漂亮,但函数也可以。如果相关的话,我正在使用MSVC。

    7 回复  |  直到 9 年前
        1
  •  15
  •   Jerry Coffin    12 年前

    编辑:更正后的函数应如下所示:

    time_t cvt_TIME(char const *time) { 
        char s_month[5];
        int month, day, year;
        struct tm t = {0};
        static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    
        sscanf(time, "%s %d %d", s_month, &day, &year);
    
        month = (strstr(month_names, s_month)-month_names)/3;
    
        t.tm_mon = month;
        t.tm_mday = day;
        t.tm_year = year - 1900;
        t.tm_isdst = -1;
    
        return mktime(&t);
    }
    
        2
  •  7
  •   tfinniga    9 年前

    杰瑞的功能看起来很好。这是我的尝试……我也投入了时间。

    #include <iostream>
    #include <sstream>
    
    using namespace std;
    
    time_t time_when_compiled()
    {
        string datestr = __DATE__;
        string timestr = __TIME__;
    
        istringstream iss_date( datestr );
        string str_month;
        int day;
        int year;
        iss_date >> str_month >> day >> year;
    
        int month;
        if     ( str_month == "Jan" ) month = 1;
        else if( str_month == "Feb" ) month = 2;
        else if( str_month == "Mar" ) month = 3;
        else if( str_month == "Apr" ) month = 4;
        else if( str_month == "May" ) month = 5;
        else if( str_month == "Jun" ) month = 6;
        else if( str_month == "Jul" ) month = 7;
        else if( str_month == "Aug" ) month = 8;
        else if( str_month == "Sep" ) month = 9;
        else if( str_month == "Oct" ) month = 10;
        else if( str_month == "Nov" ) month = 11;
        else if( str_month == "Dec" ) month = 12;
        else exit(-1);
    
        for( string::size_type pos = timestr.find( ':' ); pos != string::npos; pos = timestr.find( ':', pos ) )
            timestr[ pos ] = ' ';
        istringstream iss_time( timestr );
        int hour, min, sec;
        iss_time >> hour >> min >> sec;
    
        tm t = {0};
        t.tm_mon = month-1;
        t.tm_mday = day;
        t.tm_year = year - 1900;
        t.tm_hour = hour - 1;
        t.tm_min = min;
        t.tm_sec = sec;
        return mktime(&t);
    }
    
    int main( int, char** )
    {
        cout << "Time_t when compiled: " << time_when_compiled() << endl;
        cout << "Time_t now: " << time(0) << endl;
    
        return 0;
    }
    
        3
  •  3
  •   Bruno Bronosky    11 年前

    我不知道是否有其他Arduino黑客会偶然发现这个问题,但我发现@jerryconfim的答案对于解决我的项目中的这个问题非常有帮助。下面是一个完整的示例,您可以将其粘贴到Arduino中。它使用 Time lib referenced here .

    #include "Arduino.h"
    #include <Time.h>
    #include <stdio.h>
    
    time_t cvt_date(char const *date) { 
        char s_month[5];
        int month, day, year;
        tmElements_t tmel;
        static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    
        sscanf(date, "%s %d %d", s_month, &day, &year);
    
        month = (strstr(month_names, s_month)-month_names)/3+1;
    
        tmel.Hour = tmel.Minute = tmel.Second = 0; // This was working perfectly until 3am then broke until I added this.
        tmel.Month = month;
        tmel.Day = day;
     // year can be given as full four digit year or two digts (2010 or 10 for 2010);
     //it is converted to years since 1970
      if( year > 99)
          tmel.Year = year - 1970;
      else
          tmel.Year = year + 30;
    
        return makeTime(tmel);
    }
    
    void printdate(char const *date)
    {
      Serial.println((String)"cvt_date('" + date + "')");
      time_t t = cvt_date(date);
    
      Serial.println((String) month(t) + "-" + day(t) + "-" + year(t));
      setTime(t);
      Serial.println((String) month()  + "/" + day()  + "/" + year() + "\n");
    }
    
    void setup()
    {
      Serial.begin(9600); while (!Serial);
      printdate(__DATE__);       // works with the compiler macro
      printdate("Jan  1    00"); // works with 2 digit years
      printdate("Feb  28   01");
      printdate("Mar  7 5");     // works with 1 digit years
      printdate("Apr  10 1970"); // works from 1970
      printdate("May  13 1980");
      printdate("Jun  16 1990");
      printdate("Jul  19 1997");
      printdate("Aug  22 2000");
      printdate("Sep  25 2010");
      printdate("Oct  31 2014");
      printdate("Nov  30 2020");
      printdate("Dec  31 2105"); // through 2105
      printdate("Dec  31 2106"); // fails at and after 2106
    }
    
    void loop(){
    }
    

    以下是串行终端结果…

    cvt_date('Oct  5 2014')
    10-5-2014
    10/5/2014
    
    cvt_date('Jan  1    00')
    1-1-2000
    1/1/2000
    
    cvt_date('Feb  28   01')
    2-28-2001
    2/28/2001
    
    cvt_date('Mar  7 5')
    3-7-2005
    3/7/2005
    
    cvt_date('Apr  10 1970')
    4-10-1970
    4/10/1970
    
    cvt_date('May  13 1980')
    5-13-1980
    5/13/1980
    
    cvt_date('Jun  16 1990')
    6-16-1990
    6/16/1990
    
    cvt_date('Jul  19 1997')
    7-19-1997
    7/19/1997
    
    cvt_date('Aug  22 2000')
    8-22-2000
    8/22/2000
    
    cvt_date('Sep  25 2010')
    9-25-2010
    9/25/2010
    
    cvt_date('Oct  31 2014')
    10-31-2014
    10/31/2014
    
    cvt_date('Nov  30 2020')
    11-30-2020
    11/30/2020
    
    cvt_date('Dec  31 2105')
    12-31-2105
    12/31/2105
    
    cvt_date('Dec  31 2106')
    11-23-1970
    11/23/1970
    

    如果你只想使用 __DATE__ 你不需要 time_t tmElements_t 对象,代码可以简单得多。

    void logname(char const *date, char *buff) { 
        int month, day, year;
        static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
        sscanf(date, "%s %d %d", buff, &day, &year);
        month = (strstr(month_names, buff)-month_names)/3+1;
        sprintf(buff, "%d%02d%02d.txt", year, month, day);
    }
    
    void setup()
    {
      Serial.begin(9600); while (!Serial);
      Serial.print("log file name: ");
      char filename[16];
      logname(__DATE__, filename);
      Serial.println(filename);
    }
    
    void loop(){
    }
    

    以下是串行终端结果…

    log file name: 20141009.txt
    
        4
  •  2
  •   ptwolny    10 年前

    基于以下描述: gcc.gnu.org 编译时可以使用以下宏获取生成日期。

    #define BUILDTM_YEAR (\
        __DATE__[7] == '?' ? 1900 \
        : (((__DATE__[7] - '0') * 1000 ) \
        + (__DATE__[8] - '0') * 100 \
        + (__DATE__[9] - '0') * 10 \
        + __DATE__[10] - '0'))
    
    #define BUILDTM_MONTH (\
        __DATE__ [2] == '?' ? 1 \
        : __DATE__ [2] == 'n' ? (__DATE__ [1] == 'a' ? 1 : 6) \
        : __DATE__ [2] == 'b' ? 2 \
        : __DATE__ [2] == 'r' ? (__DATE__ [0] == 'M' ? 3 : 4) \
        : __DATE__ [2] == 'y' ? 5 \
        : __DATE__ [2] == 'l' ? 7 \
        : __DATE__ [2] == 'g' ? 8 \
        : __DATE__ [2] == 'p' ? 9 \
        : __DATE__ [2] == 't' ? 10 \
        : __DATE__ [2] == 'v' ? 11 \
        : 12)
    
    #define BUILDTM_DAY (\
        __DATE__[4] == '?' ? 1 \
        : ((__DATE__[4] == ' ' ? 0 : \
        ((__DATE__[4] - '0') * 10)) + __DATE__[5] - '0'))
    
        5
  •  1
  •   quickbug    11 年前

    布鲁诺的回答对我的阿杜诺项目非常有用。这是一个有日期和时间的版本__

    #include <Time.h>
    #include <stdio.h>
    
    time_t cvt_date(char const *date, char const *time)
    {
        char s_month[5];
        int year;
        tmElements_t t;
        static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    
        sscanf(date, "%s %hhd %d", s_month, &t.Day, &year);
        sscanf(time, "%2hhd %*c %2hhd %*c %2hhd", &t.Hour, &t.Minute, &t.Second);
    
        // Find where is s_month in month_names. Deduce month value.
        t.Month = (strstr(month_names, s_month) - month_names) / 3 + 1;
    
        // year can be given as '2010' or '10'. It is converted to years since 1970
        if (year > 99) t.Year = year - 1970;
        else t.Year = year + 30;
    
        return makeTime(t);
    }
    
    void setup()
    {
        Serial.begin(115200); 
        while (!Serial);
    
        // Show raw system strings
        Serial.println(String("__DATE__ = ") + __DATE__);
        Serial.println(String("__TIME__ = ") + __TIME__);
    
        // set system time = compile time
        setTime(cvt_date(__DATE__, __TIME__));
    
        // Show actual time
        Serial.println(String("System date = ") + month() + "/" + day() + "/" + year() + " " + hour() + ":" + minute() + ":" + second() + "\n");
    }
    
    void loop() {}
    
        6
  •  0
  •   user9876    16 年前

    回答 here .

    格式规范 日期 here .

        7
  •  0
  •   Joe Ellsworth    10 年前

    这里是我如何修改您的样本,以与MARD的ARM32微控制器在C++中使用。

    // Convert compile time to system time 
    time_t cvt_date(char const *date, char const *time)
    {
        char s_month[5];
        int year;
        struct tm t;
        static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
        sscanf(date, "%s %d %d", s_month, &t.tm_mday, &year);
        sscanf(time, "%2d %*c %2d %*c %2d", &t.tm_hour, &t.tm_min, &t.tm_sec);
        // Find where is s_month in month_names. Deduce month value.
        t.tm_mon = (strstr(month_names, s_month) - month_names) / 3 + 1;    
        t.tm_year = year - 1900;    
        return mktime(&t);
    }
    

    参见: https://developer.mbed.org/users/joeata2wh/code/compile_time_to_system_time/ 完整代码。也看到 https://developer.mbed.org/users/joeata2wh/code/xj-Init-clock-to-compile-time-if-not-alr/ 例如,我如何使用它来根据编译时间初始化时钟芯片。