2009-11-19 28 views
10

Tôi đang cố chuyển đổi chuỗi được tạo từ macro __DATE__ thành một time_t. Tôi không cần một trình phân tích cú pháp ngày/giờ đầy đủ, một cái gì đó chỉ xử lý định dạng của macro __DATE__ sẽ là tuyệt vời.Chuyển đổi chuỗi từ __DATE__ thành một time_t

Phương pháp tiền xử lý sẽ thuận tiện, nhưng chức năng cũng sẽ hoạt động. Nếu nó có liên quan, tôi đang sử dụng MSVC.

Trả lời

14

Edit: các chức năng điều chỉnh nên tìm một cái gì đó như thế này:

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); 
} 
+0

Một điều lớn - tháng 'trả về' bởi '__DATE__' có dạng tên ('Jan', 'Feb', v.v ...). Một gợi ý nhỏ khác: bạn nên đặt 't.tm_dst = -1' để' mktime() 'sẽ cố gắng sử dụng DST thích hợp. –

+0

@Michael - có vẻ như t.tm_dst không phải là một phần của visual C++. – tfinniga

+0

Tôi xin lỗi - đó phải là 't.tm_isdst = -1' –

6

chức năng Jerry trông tuyệt vời. Đây là nỗ lực của tôi .. Tôi cũng đã ném vào __TIME__.

#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; 
} 
+1

Không nên là 't.tm_hour = giờ - 1;'? https://msdn.microsoft.com/en-us/library/windows/hardware/ff567981(v=vs.85).aspx – gmas80

+0

Bắt tốt @ gmas80, tôi sẽ chỉnh sửa để sửa. – tfinniga

0

Trả lời here.

Thông số kỹ thuật cho định dạng DATEhere.

2

Tôi không biết liệu có tin tặc Arduino nào khác sẽ vấp phải câu hỏi này hay không, nhưng tôi thấy câu trả lời của JerryCoffin khá hữu ích trong việc giải quyết vấn đề này cho dự án của tôi. Đây là một ví dụ hoàn chỉnh bạn có thể dán vào Arduino. Nó sử dụng 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(){ 
} 

Đây là kết quả ga Serial ...

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 

Nếu tất cả các bạn muốn là sử dụng __DATE__ và bạn không cần một time_t hoặc tmElements_t đối tượng, các mã có thể được đơn giản hơn nhiều .

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(){ 
} 

Đây là kết quả ga Serial ...

log file name: 20141009.txt 
1

phản ứng Bruno là rất hữu ích cho dự án Arduino của tôi. Dưới đây là một phiên bản với cả hai __DATE__ và __TIME__

#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() {} 
1

Căn cứ vào mô tả được đưa ra tại gcc.gnu.org ngày xây dựng có thể có được tại thời gian biên dịch sử dụng các macro sau.

#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')) 
1

Đây là cách tôi sửa đổi mẫu của bạn để sử dụng với mbed cho bộ điều khiển vi mô Arm32 trong 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); 
} 

Xem: https://developer.mbed.org/users/joeata2wh/code/compile_time_to_system_time/ để có mã hoàn chỉnh. Ngoài ra, hãy xem https://developer.mbed.org/users/joeata2wh/code/xj-Init-clock-to-compile-time-if-not-alr/ để biết ví dụ về cách tôi sử dụng nó để khởi tạo chip đồng hồ dựa trên thời gian biên dịch.

Các vấn đề liên quan