Search code examples
cdatebyteascii

Convert ISO String Date to %d-%m-%Y %H%M%S in C


I have a ASCII array (converted String date format 2023-26-04T12:01:42.123+01:00) The byte array is now:

 2023-04-26T12:01:42.123+01:00
 32 30 32 33 2D 30 34 2D 32 36 54 30 39 3A 31 31 3A 35 37 2E 39 36 37 2B 30 39 3A 31 31  

The format of final date must be in

 DD-MM-YYYY HHmmss (parse ascii bytes and trim).

Is there any function in C which can help in conversion. So far I have done, but seems incorrect:

void convertUTCTimeto24HourFormat(const void* data)
{
    char buf[sizeof "24-04-2023 245957"]; //sample to know size
    struct tm tm;
    /* 1. Convert buffer to time struct */
    memset(&tm, 0, sizeof(struct tm));
    /* 2. strip the time and zone from data */    
    (void)strptime(data, "%FT%TZ", &tm);
    strftime(buf, sizeof(buf), "%d-%m-%Y %H%M%S", &tm);  
}  

Is struct tm not the way? Or creating char array and parsing one by one (conversion from ascii to hex and back seems tedious)


Solution

  • Is there any function in C which can help in conversion(?)

    Yes, strptime()/strftime() are useful, when available. See below.

    Is struct tm not the way?

    struct tm is one way to do this.


    Problems with (void)strptime(data, "%FT%TZ", &tm);

    • strptime() is not a standard C library function. Various systems define it like this.

    • "%FT%TZ" likely should be "%FT%T%z": Add % , z for offset, not Z name.

    • Ignoring the return value. Good code checks the return value for errors.

    OP's ASCII array lacks a null character, needed for strptime().


    Untested alternative:

    // Return error flag
    int convertUTCTimeto24HourFormat(size_t buf_size, char *buf, const void* data) {
        // Copy data and append a \0
        char source[sizeof "2023-04-26T12:01:42.123+01:00"];
        strncpy(source, data, sizeof source - 1);
        source[sizeof source - 1] = '\0';
        
        //  Parse string
        char buf[sizeof "24-04-2023 245957"];
        struct tm tm = { 0 };// Use this instead of memset().
        if (strptime(source, "%FT%T%z", &tm) == NULL) {
          return 1;
        }
    
        // Form new string.
        if (strftime(buf, buf_size, "%d-%m-%Y %H%M%S", &tm) == 0) {
          return 2;
        }
        puts(buf);
        return 0;
    } 
    

    Ref: ISO-8601.

    Assume OP's typo:

    (converted String date format 2023-26-04T12:01:42.123+01:00) Original
    (converted String date format 2023-04-26T12:01:42.123+01:00) Change in month/day
    

    OP's sample byte array is questionable

    04-26T12:01:42.123+01:00
    32 30 32 33 2D 30 34 2D 32 36 54 30 39 3A 31 31 3A 35 37 2E 39 36 37 2B 30 39 3A 31 31  
    

    I suspect it is instead

     2  0  2  3  -  0  4  -  2  6  T  0  9  :  1  1  :  5  7  .  9  6  7  +  0  9  :  1  1
    32 30 32 33 2D 30 34 2D 32 36 54 30 39 3A 31 31 3A 35 37 2E 39 36 37 2B 30 39 3A 31 31