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"); }