Arduino Forum

Using Arduino => Programming Questions => Topic started by: arsalh on Feb 29, 2016, 09:55 pm

Title: Extracting hour/minute/second/date from String
Post by: arsalh on Feb 29, 2016, 09:55 pm
Can someone help me with converting a string to day/date/hour/sec/minute etc into separate variables?
I have a string that contains date/time and want to use it to set time using Arduino's Time Library.


STRING TO CONVERT:      "Date: Mon, 29 Feb 2016 12:02:00 GMT"
FUNCTION TO USE:          setTime(hr,min,sec,day,month,yr);

So from the string above, I want to extract hour, minute, seconds, day, month and year into variables. I am trying to do this on an Arduino Uno.
Title: Re: Extracting hour/minute/second/date from String
Post by: aarg on Feb 29, 2016, 10:15 pm
Well, as you can imagine, it will be a huge pain. So, I have to ask, why do you need to read the time in this format? Perhaps we can suggest a better alternative if you explain the reason.
Title: Re: Extracting hour/minute/second/date from String
Post by: arsalh on Feb 29, 2016, 10:29 pm
Hey I am trying to get accurate time for my project. I am using ESP8266 and want to keep track of the time in the project. I have seen the API methods for getting time but it seems to me that those take a little longer. So what I am doing instead is that I am extracting the time/date from the GET response I receive when I try to open a JSON file stored on a web server. Since I am opening the JSON file either way for my project, I wouldn't have to connect to a separate host to get time/date if I do it this way.

I may be super wrong in my assumptions but I just thought that might be the better way of approaching this. Let me know what you think.
Title: Re: Extracting hour/minute/second/date from String
Post by: aarg on Feb 29, 2016, 10:47 pm
Oh, yeah. I've noticed that string. I thought about tapping into it. Have you thought about using NTP? There is an NTP example in the Ethernet library. The example shows how to convert the time to a format that the Time library can import.

Just be a good netizen and don't poll the NTP server more than once a few minutes.

Or even easier, use an accurate RTC.

Otherwise, I don't believe there is an easy answer, it will just be lines and lines of dull plodding parsing code.

Note that DateStrings.cpp in the Time Library has the strings you need, e.g.
Code: [Select]
const char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec";
Title: Re: Extracting hour/minute/second/date from String
Post by: PaulS on Mar 01, 2016, 12:06 am
Quote
Can someone help me with converting a string to day/date/hour/sec/minute etc into separate variables?
Is the data in a string, as this question suggests? Or, is it in a String, as the thread topic suggests.

Parsing a string is easy. Parsing a String is a pain in the ass.
Title: Re: Extracting hour/minute/second/date from String
Post by: Jon_White on Mar 01, 2016, 01:42 am
Try this.  As long as the date is always well-formed, it should work...

Code: [Select]
#include "stdafx.h"

int ParseDatePart(int partNumber, char* pDate)
{
// Find the right part using space and colon as delimiters.  Return -1 if we run out of parts.
int index = 0;
while (partNumber)
{
if (pDate[index] == ':' || pDate[index] == ' ') partNumber--;
if (!pDate[++index]) return -1;
}

// If the part starts with a digit, read all of the digits.
int result = 0;
while (pDate[index] >= '0' && pDate[index] <= '9')
{
result = result * 10 + pDate[index++] - '0';
if (pDate[index] < '0' || pDate[index] > '9') return result;
}

// Otherwise, read it as a month.
switch (pDate[index++])
{
case 'J':
if (pDate[index] == 'a') return 1;
if (pDate[index++] && pDate[index] == 'n') return 6;
return 7;
case 'F':
return 2;
case 'M':
if (pDate[index++] && pDate[index] == 'r') return 3;
return 5;
case 'A':
if (pDate[index] == 'p') return 4;
return 8;
case 'S':
return 9;
case 'O':
return 10;
case 'N':
return 11;
case 'D':
return 12;
}

// Return -1 if it didn't parse as either a number or a month.
return -1;
}

int main(int argc, char** argv)
{
if (argc < 2)
{
printf("Usage:   foo <date>\r\n");
printf("Example: foo \"Date: Mon, 29 Feb 2016 12:02:00 GMT\"\r\n");
return 1;
}
char* pDate = argv[1];
int day = ParseDatePart(3, pDate);
int month = ParseDatePart(4, pDate);
int year = ParseDatePart(5, pDate);
int hour = ParseDatePart(6, pDate);
int minute = ParseDatePart(7, pDate);
int second = ParseDatePart(8, pDate);
printf("%d/%d/%d %d:%d:%d\r\n", month, day, year, hour, minute, second);
return 0;
}
Title: Re: Extracting hour/minute/second/date from String
Post by: zoomkat on Mar 01, 2016, 05:11 am
Quote
So from the string above, I want to extract hour, minute, seconds, day, month and year into variables. I am trying to do this on an Arduino Uno.
If the character string received is captured as a String, then the various String functions can be used to extract the desired data.
Title: Re: Extracting hour/minute/second/date from String
Post by: -dev on Mar 01, 2016, 03:38 pm
Don't use String.  The solutions using C strings (i.e., char arrays) are very efficient.

String will add at least 1600 bytes of FLASH to your program size and 10 bytes per String variable.  Although String is fairly easy to use and understand, it will also cause random hangs and crashes as your program runs longer and/or grows in size and complexity.  This is due to dynamic memory (https://en.wikipedia.org/wiki/C_dynamic_memory_allocation) fragmentation (https://en.wikipedia.org/wiki/Fragmentation_(computing))  caused by the heap management routines malloc and free.

The most recent example of the pitfalls of String can be seen here (http://forum.arduino.cc/index.php?topic=380172.0).

Related forum discussions:
Commentary from systems experts elsewhere on the net:
Cheers,
/dev