|
Home > Archive > Unix Programming > September 2006 > GNU getdate, portability, parsing dates
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
GNU getdate, portability, parsing dates
|
|
| Daniel C. Bastos 2006-09-17, 1:28 am |
| Hi. Is there any portable function that can parse some date
formats and return a UNIX timestamp?
I see that there seems to exist a function called getdate in the
GNU C library, but I don't seem to have this function in my
libc. My system is a
FreeBSD my.free.dom.to 4.11-STABLE FreeBSD 4.11-STABLE,
so I suppose we don't use the GNU C library here. If this
function is not available in systems such as freebsd, then I
guess I would not really want to use it for now. Any advice?
| |
| Henry Townsend 2006-09-17, 1:28 am |
| Daniel C. Bastos wrote:
> Hi. Is there any portable function that can parse some date
> formats and return a UNIX timestamp?
The POSIX functions for this are strftime() and strptime(). POSIX is
about as portable as you're going to get.
| |
| William Ahern 2006-09-20, 7:52 pm |
| On Sun, 17 Sep 2006 02:23:44 +0000, Daniel C. Bastos wrote:
> Hi. Is there any portable function that can parse some date formats and
> return a UNIX timestamp?
>
> I see that there seems to exist a function called getdate in the GNU C
> library, but I don't seem to have this function in my libc. My system is a
>
> FreeBSD my.free.dom.to 4.11-STABLE FreeBSD 4.11-STABLE,
>
> so I suppose we don't use the GNU C library here. If this function is not
> available in systems such as freebsd, then I guess I would not really want
> to use it for now. Any advice?
It appears to be standardized:
http://www.opengroup.org/onlinepubs...ns/getdate.html
Though, that doesn't help. But, the description does. It would appear easy
to implement getdate() by employing strptime() and looping over
format strings (e.g. the suggested formats in the SUSv3 spec) yourself.
| |
| Daniel C. Bastos 2006-09-24, 1:21 pm |
| In article <pan.2006.09.21.00.24.16.661414@25thandClement.com>,
William Ahern wrote:
> On Sun, 17 Sep 2006 02:23:44 +0000, Daniel C. Bastos wrote:
>
>
> It appears to be standardized:
>
> http://www.opengroup.org/onlinepubs...ns/getdate.html
>
> Though, that doesn't help. But, the description does. It would appear easy
> to implement getdate() by employing strptime() and looping over
> format strings (e.g. the suggested formats in the SUSv3 spec) yourself.
That's a nice idea. I had actually chosen to stick to one format
and just use strptime() which is good enough for my application
--- though it's nice to offer the user a smart program that can
understand lots of formats.
The nice thing about getdate(), as it seems from the description
on the URL above, is that it checks for some invalid dates; for
example, it checks that February 31 is invalid. I wonder whether
it checks for leap years too.
Checking dates seems rather boring. I had to write a ``lenghty''
function to do all the necessary checkings such as leap years ---
which, by the way, if there's any hole in it, I'd appreciate the
criticism. As far as I'm able to check, checkdate() accuses all
invalid dates between January 1st 1970 and January 18th 2038. I'm
excluding all the valid hours --- using a long UNIX timestamp ---
in January 18th 2038 to simplify.
static int checkdate(struct tm *t)
{
unsigned int y; unsigned int feb;
if (t->tm_year + 1900 < 1970) return -18;
if (t->tm_year + 1900 > 2038) return -19;
if (t->tm_year + 1900 == 2038) {
if (t->tm_mon != 0) return -20;
if (t->tm_mday < 1 || t->tm_mday > 18) return -21;
}
/* month range: 0 .. 11 */
if (t->tm_mon > 11 || t->tm_mon < 0) return -17;
switch(t->tm_mon) {
/* jan, mar, may, jul, aug, oct, dec */
case 0: case 2: case 4: case 6: case 7: case 9: case 11:
if (t->tm_mday < 1 || t->tm_mday > 31) return -1;
break;
/* abr, jun, sep, nov */
case 3: case 5: case 8: case 10:
if (t->tm_mday < 1 || t->tm_mday > 30) return -2;
break;
case 1: /* feb */
y = 1900 + t->tm_year; /* leap year? */
if ( !(y % 4) && (!(y % 100) || (y % 400)) ) feb = 29; else feb = 28;
if (t->tm_mday < 1 || t->tm_mday > feb) return -3;
break;
}
return 0;
}
|
|
|
|
|