Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!bunyip.cc.uq.oz.au!munnari.OZ.AU!news.ecn.uoknor.edu!news.ysu.edu!usenet.ins.cwru.edu!magnus.acs.ohio-state.edu!math.ohio-state.edu!howland.reston.ans.net!vixen.cso.uiuc.edu!newsfeed.internetmci.com!tank.news.pipex.net!pipex!news.mathworks.com!uunet!in1.uu.net!gti.gti.net!dkinney
From: dkinney@gti.net (David Kinney)
Newsgroups: comp.unix.programmer,comp.unix.bsd.freebsd.misc
Subject: Re: string -> time_t routine, anyone?
Followup-To: comp.unix.programmer,comp.unix.bsd.freebsd.misc
Date: 22 Mar 1996 23:38:28 GMT
Organization: GTI GlobalNet - (201) 285-9099
Lines: 265
Message-ID: <4ivdlk$jq@gti.gti.net>
References: <1996Mar21.083253.22259@wavehh.hanse.de>
NNTP-Posting-Host: apollo.gti.net
X-Newsreader: TIN [version 1.2 PL2]
Xref: euryale.cc.adfa.oz.au comp.unix.programmer:35440 comp.unix.bsd.freebsd.misc:15780
Martin Cracauer (cracauer@wavehh.hanse.de) wrote:
: I need a routine to convert a string like "19960302" (or other syntax)
: to a time_t. I thought about using the source of date(1), but maybe
: someone has done this before?
Hi Martin.
Below is my program "not_ctime.c" which does basically what
you want. You may need to modify it slightly depending on
the input format you use.
Hope this helps,
David Kinney dkinney@gti.net
/******************************************************************************
*
*
* Program: not_ctime
* ========
*
* Reverse the effects of my 'ctime.c' program.
* If you input a string such as the default format output
* of 'date':
*
* not_ctime Mon Dec 18 20:38:52 EST 1995
*
* "not_ctime" will return the absolute number of seconds since
* since the beginning of the epoch (Jan. 1 1970). E.g.:
*
* The time_since_epoch is 819337132 sec.
*
*
* My "ctime" program takes the absolute number of seconds
* since the beginning of the epoch, e.g. ctime 819337132
* and returns a default format 'date' string. E.g.:
*
* Mon Dec 18 20:38:52 EST 1995
*
*
* "not_ctime" will be useful when you're trying to determine
* the elapsed time between two calendar dates. E.g. between:
* Mon May 17 16:20:17 EST 1954 and
* Mon Dec 18 20:38:52 EST 1995
*
* See also my programs 'ctime', 'difftime', and
* 'sec_to_time_string'.
*
*
* Input: A string such as the default format output of 'date'.
* ====== E.g. Mon Dec 18 20:38:52 EST 1995
*
* Specifically, the format is:
* day_of_week month_name month_date, time_string time_zone year
*
* Since "not_ctime" ignores the "day_of_week" and "time_zone"
* fields, you could put garbage in them, but there has to be
* something in these two fields so that the argv[] counts are
* correct.
*
*
* Output: Outputs the absolute number of seconds since
* ======= since the beginning of the epoch (Jan. 1 1970). E.g.
*
* The time_since_epoch is 819337132 sec.
*
*
* Error Handling: There are 3 possible error conditions:
* ===============
* 1. Number of input args. (argc) != 7
* There must be the name of this command + 6 other args.
*
* 2. Read in non-month string (e.g. XXX) when expecting a
* month string such as "Dec".
*
* 3. (year < 1900) || (year > 2038)
* 'mktime()' will only handle years between 1900 - 2038.
* Anything else is out of range.
*
* All these errors cause 'print_usage' to be called then
* exit() the program. Note that the exit() is called
* immediately *after* 'print_usage()' returns. exit() is not
* called from 'print_usage()'
*
* 'print_usage(argv[0])' prints to stderr:"
*
* Usage: not_ctime day_of_week month_name month_date, time_string time_zone year
* Ex: Mon Dec 18 20:38:52 EST 1995
*
*
* Routines: print_usage()
* =========
*
*
* Calls: mktime()
* ======
*
*
* Programmer: David Kinney
* ===========
*
*
* Date: Mon. Dec. 18, 1995
* =====
*
*
* Comments: There are *13* routines such as 'ctime()' that
* ========= "convert date and time to string". However,
* the only way to do the reverse is to use a
* side-effect of 'mktime()'. This is what
* "not_ctime" does.
*
*
* REVISION HISTORY
* ================
*
* Date | Who | Comments
* =========================================================================
* | |
* 12/18/95 | DK | Created
* | |
******************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#define ILLEGAL_MONTH_NR -1
#define MATCH 0
/* From 'man mktime()':
"The tm structure contains the following members:
int tm_sec; seconds after the minute [0, 61]
int tm_min; minutes after the hour [0, 59]
int tm_hour; hour since midnight [0, 23]
int tm_mday; day of the month [1, 31]
int tm_mon; months since January [0, 11]
int tm_year; years since 1900
int tm_wday; days since Sunday [0, 6]
int tm_yday; days since January 1 [0, 365]
int tm_isdst; flag for daylight savings time
....
tm_year of the tm structure must be for year 1970 or later.
Calendar times before 00:00:00 UTC, January 1, 1970 or after
03:14:07 UTC, January 19, 2038 cannot be represented."
I don't need the fields "tm_wday" and "tm_yday" so I don't set them.
However, 'mktime()' will automatically fill them in.
This program accepts input for "tm_mon" as a month name (e.g.
"Dec"), converts it to a number (e.g. 11) which falls in the [0-11]
range needed for "tm_mon".
*/
struct tm time_str;
time_t time_since_epoch;
char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
int month_nr;
int hours, minutes, seconds, year;
main(argc, argv)
int argc;
char *argv[];
{
int i;
if (argc != 7)
{
print_usage(argv[0]);
exit();
}
/* We don't use argv[1], the day_name. E.g. "Mon" */
/* Convert the month str, e.g. "Dec" to a month number, e.g. 11.
Note: the month number will be one less than usual (e.g. "Dec"
is 11) 'cause "time_str.tm_mon" expects not the month number,
but rather the number of months *since* Jan. [0-11] */
month_nr = ILLEGAL_MONTH_NR;
for (i = 0; i <= 11; i++)
if (strcmp(months[i], argv[2]) == MATCH)
{
month_nr = i;
break;
}
if (month_nr == ILLEGAL_MONTH_NR)
{
printf("\n\nERROR: Read in non-month string \"%s\", when\n");
printf(" expected to get a month string such as \"Dec\".\n\n", argv[2]);
print_usage(argv[0]);
exit();
}
time_str.tm_mon = month_nr;
time_str.tm_mday = atoi(argv[3]);
/* argv[4] is a string with the format hh:mm:ss E.g. 21:05:32 */
sscanf(argv[4], "%d:%d:%d",
&time_str.tm_hour, &time_str.tm_min, &time_str.tm_sec);
/* We don't use argv[5], the time zone. E.g. "EDT" */
year = atoi(argv[6]);
if ( (year < 1900) || (year > 2038) )
{
print_usage(argv[0]);
exit();
}
else
year -= 1900;
/* "year" should now contain the nr. of years since 1900 ! E.g. 95 */
time_str.tm_year = year;
/* Don't know if daylight savings time is in effect or not. By setting
this variable to -1, 'mktime()' will figure it out and adjust for it. */
time_str.tm_isdst = -1;
time_since_epoch = mktime(&time_str);
if ( time_since_epoch == -1)
{
printf("\nThe calendar time cannot be represented\n\n");
print_usage(argv[0]);
exit();
}
printf("\nThe time_since_epoch is %d sec.\n\n", time_since_epoch);
}
print_usage(program_name)
char *program_name;
{
fprintf(stderr, "\nUsage: %s day_of_week month_name month_date, time_string time_zone year\n", program_name);
fprintf(stderr, " Ex: Mon Dec 18 20:38:52 EST 1995\n\n");
}