簡體   English   中英

從 C 中的字符串解析日期和時間

[英]parsing date and time from a string in C

我試圖從調制解調器得到的以下響應中解析日期和時間。 響應存在於 BG96_TmpBuffer 緩沖區中。

+CCLK: "21/03/29,16:17:13+52"

 OK

我為它開發了以下function。

uint8_t BG96_parseNetworkTime(uint8_t *year_out, uint8_t *month_out, uint8_t *day_out, uint8_t *hour_out,
                                uint8_t *min_out, uint8_t *sec_out, uint8_t *timezone_out){
        //Extract the date and time
        printf("Parsing: %s\r\n", BG96_TmpBuffer);
        
        uint8_t num = sscanf((char*)BG96_TmpBuffer,
        "%hhu %hhu %hhu %hhu %hhu %hhu %hhu",
        *year_out,
        *month_out,
        *day_out,
        *hour_out,
        *min_out,
        *sec_out,
        *timezone_out);
        
        //Check if it was successful
        if(num > 0){
            printf("Date: %u/%u/%hu\r\n", *day_out, *month_out, *year_out);
            printf("Time: %u:%u:%u\r\n", *hour_out, *min_out, *sec_out);
            return true;
        }
        
    return false;                           
}

當我測試 function 時,它不起作用。 sscanf 總是返回 0。我做了以下測試代碼。

        uint8_t year = 0, month = 0, day = 0, hour = 0, min = 0, secs = 0, timezone = 0;
        bool status = BG96_parseNetworkTime(&year, &month, &day, &hour, &min, &secs, &timezone);

有人可以建議為什么上述方法不起作用以及我做錯了什么?

編輯 1:在輸入 function 時,將打印 BG96_TmpBuffer,如下所示。

Parsing:
+CCLK: "21/03/30,10:48:30+52"

OK

編輯 2:添加整個 API。

/****************************************************************
 * Function Name    : BG96_synchronizeTime
 * Description      : Set the RTC time via BG96
 * Returns          : 0 on in progress, 1 on OK, -1 on error
 * Params           None.
 ****************************************************************/
int8_t BG96_synchronizeTime(void){
    enum BG96_syncTimes_t {GET_CCLK, UPDATE_CCLK, REBOOT, REBOOT_WAIT, GET_TIME, SET_TIME, OK, ERROR};
    static enum BG96_syncTimes_t state = GET_CCLK;
    static bool timeSync = false;
    static int8_t syncStatus = false;
    
    syncStatus = false; //this will be updated later
    
    if(timeSync){//Already synchronized
        printf("[BG96 CLK], ### Already synchronized ###\r\n");
        return true;
    }
    
    switch(state){
        case GET_CCLK:{
            //Get the current clock time
            int8_t status = BG96_sendCommand((char*)"AT+CCLK?\r", strlen("AT+CCLK?\r"), sBG96_OK, NULL, NULL, NULL, 1000, 1);
            if(status == false) {
                //Operation in progress
            } else if(status == -1) {
                state = ERROR;
            } else if(status == true ){
                state = UPDATE_CCLK;        //valid ans1
            } else {
                //Should never arrive here
            }
        }
        break;
        
        case UPDATE_CCLK:{
            //Update the clock time to GMT via NITZ
            int8_t status = BG96_sendCommand((char*)"AT+CTZU=3\r", strlen("AT+CTZU=1\r"), sBG96_OK, NULL, NULL, NULL, 1000, 1);
            if(status == false) {
                //Operation in progress
            } else if(status == -1) {
                state = ERROR;
            } else if(status == true ){
                state = REBOOT;     //valid ans1
            } else {
                //Should never arrive here
            }
        }
        break;
        
        case REBOOT:{
            //Reset the ME, all the above will take effect after this reset
            int8_t status = BG96_sendCommand((char*)"AT+CFUN=1,1\r", strlen("AT+CFUN=1,1\r"), sBG96_OK, NULL, NULL, NULL, 5000, 1);
            if(status == false) {
                //Operation in progress
            } else if(status == -1) {
                 state = ERROR; //no answer or error
            } else if(status == true) {
                 _cfun_waitComplete = false;
                 EventTimerCreate(10000,    1,  BG96_cfunWaitCompleteCb);
                 state = REBOOT_WAIT; //valid ans1
            } else {
                  // Should never arrive here
            }
        }
        break;
        
        case REBOOT_WAIT:{
            //Wait for the ME to scan the bands
            if(_cfun_waitComplete == true) {
                state = GET_TIME;
            } else {
                //Wait here
            }
        }
        break;
        
        case GET_TIME:{
            //Get the current clock time
            int8_t status = BG96_sendCommand((char*)"AT+CCLK?\r", strlen("AT+CCLK?\r"), "+", NULL, NULL, NULL, 1000, 1);
            if(status == false) {
                //Operation in progress
            } else if(status == -1) {
                state = ERROR;
            } else if(status == true ){
                state = SET_TIME;       //valid ans1
            } else {
                //Should never arrive here
            }
        }
        break;
        
        case SET_TIME:{
            uint8_t year = 0, month = 0, day = 0, hour = 0, min = 0, secs = 0, timezone = 0;
            bool status = BG96_parseNetworkTime(&year, &month, &day, &hour, &min, &secs, &timezone);
            state = OK;
        }
        break;
        
        case OK:{
            BG96_resetTmpRxBuffer();
            state = GET_CCLK;
            timeSync = true;
            syncStatus = true;
        }
        break;
        
        case ERROR:{
            BG96_resetTmpRxBuffer();
            state = GET_CCLK;
            timeSync = false;
            syncStatus = -1;
        }
        break;
        
        default:
        break;
    }
    
    return syncStatus;
}

如 kaylum 評論中所述,您必須匹配輸入字符串的格式:

uint8_t BG96_parseNetworkTime(uint8_t *year_out, uint8_t *month_out, uint8_t *day_out, uint8_t *hour_out,
                                uint8_t *min_out, uint8_t *sec_out, uint8_t *timezone_out){
        //Extract the date and time // "21/03/29,16:17:13+52"
        printf("Parsing: %s\r\n", BG96_TmpBuffer);
        
        uint8_t num = sscanf((char*)BG96_TmpBuffer,
        "%hhu/%hhu/%hhu,%hhu:%hhu:%hhu+%hhu",
        year_out,
        month_out,
        day_out,
        hour_out,
        min_out,
        sec_out,
        timezone_out);
        
        //Check if it was successful
        if(num == 7){
            printf("Date: %u/%u/%hu\r\n", *day_out, *month_out, *year_out);
            printf("Time: %u:%u:%u\r\n", *hour_out, *min_out, *sec_out);
            return true;
        }
        
    return false;                           
}

注意:請注意,響應可能是不同的格式,因為歐洲人會顛倒日期和月份,如果你確定你的調制解調器會被定位,那就沒問題了。 但老實說,自紀元以來以秒為單位的時間戳(以及解析)的長值會更好。

我強烈建議您使用strptime function,它由標准 C 庫提供,用於此確切目的,除非您想為教育目的推出自己的。 它的原型是char *strptime(const char *s, const char *format, struct tm *tm);

查看其手冊頁以獲取更多信息。 例如,您可以在http://manpagesfr.free.fr/man/man3/strptime.3.html找到它

下面是一個工作功能/解決方案。

uint8_t BG96_parseNetworkTime(int *year_out, int *month_out, int *day_out, int *hour_out,
                            int *min_out, int *sec_out, int *timezone_out){
    
    // Extract the date and time // "21/03/29,16:17:13+52"
    printf("date & time: %s\r\n", BG96_TmpBuffer);
    
    // Search first occurrence of "
    char *ptr = strstr((char*)BG96_TmpBuffer, "\"");
    if(ptr == NULL){
        printf("Error parsing the date & time\r\n");
        return false;
    }
    
    // Skip the " for parsing
    ptr++;
    printf("parsing: %s\r\n", ptr);
    uint8_t num = sscanf(ptr, "%d/%d/%d,%d:%d:%d+%d",
    year_out,
    month_out,
    day_out,
    hour_out,
    min_out,
    sec_out,
    timezone_out);
    
    // Convert year to 21st century
    *year_out = *year_out + 2000;
    
    //Check if it was successful
    if(num == 7){
        printf("Date: %d/%d/%d\r\n", *day_out, *month_out, *year_out);
        printf("Time: %d:%d:%d\r\n", *hour_out, *min_out, *sec_out);
        printf("Timezone: %d\r\n", *timezone_out);
        return true;
    }
    
    return false;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM