[英]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.