SUMMARY #2: Timestamp conversion utility

From: Robin Kinzy (netman%orwell@ra.mcs.anl.gov)
Date: Tue May 30 1995 - 11:38:40 CDT


My apologies to everyone for not sending out the solutions to my original
request for a unix timestamp conversion utility. I was rushed for time that
day preparing for the long holiday weekend, and totally spaced putting in
the solutions! <red face> Thanks to everyone (well, almost!) for reminding
me to do it eventually. And thanks again to those below that replied. We
have a successful solution now. I appreciate the resourcefulness and
willingness of this group to help.

For those interested, we are taking Sun Net Manager traps and filtering out
the ones we don't want to be sent to our pagers, based on time of day and
trap type. The traps only have the date:time as that wonderful 9-digit time
stamp...not very human readable.

Hope everyone had a great holiday!

Robin

===============================================================================

Original request:

Is there a utility program (NOT a C routine) that will take a time
stamp in "seconds since Jan. 1, 1970" format and output it in human
readable format? I'm specifically looking for the hour:minute in
the timestamp for a shell script. We are running SunOS 4.1.3_U1.

Responses:

===============================================================================
From: scowles@pangolin.Stanford.EDU (S. Cowles)

here's one implementation. save as ctime.c and then
compile with "cc -o ctime ctime.c".

/*
ctime.c: get clock time, given seconds since 00h00 GMT, 1 jan 1970
author: scowles@shgc.stanford.edu, 88/02/29 16:05:37
*/
 
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
 
#define BSD /**/
/*efine SYSV /**/
 
#ifdef SYSV
#include <macros.h> /**/
/* <macros.h> includes <sys/stat.h> and requires <sys/types.h> */
#define SB Statbuf
#endif
 
#ifdef BSD
#include <sys/stat.h>
#define SB buf
#define exists(file) (stat(file,&SB)<0 ? 0:SB.st_mode)
#define SCCSID(arg) static char Sccsid[]="arg"
#endif
 
SCCSID(@(#)ctime.c 1.1 16:05:37 88/02/29);
 
main(argc,argv) int argc; char **argv;
{
        char *ctime();
        long int atol(),i;
        if(argc!=2){
                fprintf(stderr,"usage: std seconds\n");
                exit(2);
        }
 
        i=atol(argv[1]);
        fprintf(stdout,"%s",ctime(&i));
}

===============================================================================
From: David Trueman <david@cs.dal.ca>

Gawk (the GNU implementation of awk) has a strftime routine that takes
a Unix time stamp and converts to a string following a format as used for
strftime(3). Here is our /local/bin/putdate routine:

#! /bin/sh

PATH=/local/bin:/usr/bin:/usr/ucb ; export PATH

case "$#" in
0|1) ;;
2) fmt="$1" ; shift ;;
*) echo "Usage: putdate [format] [seconds]" >&2 ; exit 2 ;;
esac

gawk -v time="$1" -v fmt="$fmt" '
BEGIN {
        if (time == "")
                time = systime()
        if (fmt == "")
                fmt = "%a %h %e %T %Z %Y"
        print strftime(fmt, time)
}
'

===============================================================================
From: Glenn.Satchell@uniq.com.au (Glenn Satchell - Uniq Professional Services)

You could write a 5 line C program and call this from your shell
scripts? The appropriate library function is ctime(3).

===============================================================================
From: blymn@awadi.com.AU (Brett Lymn)

To my knowledge, not as standard, but you can used the "ctime" package
that comes with perl to do this for you.

===============================================================================
From: Jim Wright <jwright@phy.ucsf.edu>

off the top of my head...

#include <stdio.h>
#include <time.h>
main(int argc, char *argv[])
{
    time_t t;
    t = atoi(argv[1]);
    printf(ctime(&t));
}

obviously you may want to make it a bit more robust. notice that
if you compile this, the executable is the utility you want.

===============================================================================
From: mismxb@cascade.santos.com.au (Matthew Ball)

  I needed something to do the same thing, so I wrote a C-programme which
I use in several shell scripts, called showtime:

    showtime 801301888

returns

    Wed May 24 17:21:28 1995

Feel free to stuff around with the source code, or use cut to get the hour:min

e.g. showtime 801301888 | cut -c12-16

[showtime binary deleted to save bandwidth. Contact myself or
 Matthew Ball if you would like it, but here's the C code]

/* simple C programme to output the time in various formats */
/* Syntax : showtime [-diff] <time_in_seconds_from_Jan_1_1970> */
/* Returns: Specified date/time in a nice readable format
        or (-diff) difference in that time to the current time in hours ! */
/* by M.A.Ball @ Santos , 04/08/93 */
#include <time.h>
#include <stdio.h>

void prttime();
void usage();
long chr2tim();

main(argc,argv)
int argc;
char *argv[];
{
  long t,pt;
  int i,ch,df,fi,sr;
  char line[50],dstr1[50],dstr2[50];

  time(&t);

  sprintf(dstr1,"");

  df=0;
  fi=1;
  ch=0;
  sr=0;
  if(argc>1)
  {
    for(i=1;i<argc;i++)
    {
      if(argv[i][0] == '-')
      {
        if(strcmp(argv[i],"-diff") == 0)
          df=1;
        else if(strcmp(argv[i],"-chr") == 0)
          ch=1;
        else if(strcmp(argv[i],"-srt") == 0)
          sr=1;
        else
        {
          usage(argv[0]);
          exit(4);
        }
      }
      else
      {
        fi=0;
        if(ch)
        {
          if(dstr1[0] == '\0')
            sprintf(dstr1,"%s",argv[i]);
          else
          {
            sprintf(dstr2,"%s %s",dstr1,argv[i]);
            strcpy(dstr1,dstr2);
          }
        }
        else
          pt=atoi(argv[i]);
      }
    }
  }

  if(ch)
    pt=chr2tim(dstr1);
    
  if(fi == 1)
  {
    while(gets(line) != NULL)
    {
      if(ch)
        pt=chr2tim(line);
      else
        pt=atoi(line);
      prttime(pt,t,df,ch,sr);
    }
  }
  else
  {
    prttime(pt,t,df,ch,sr);
  }
}

void prttime(t,c,d,h,s)
long t,c;
int d,h,s;
{
  int i;
  char otm[100];
  struct tm *m;

  if(d == 1)
  {
    i = (int) ((c-t)/3600);
    printf("%i\n",i);
  }
  else
  {
    if(h)
      printf("%i\n",t);
    else
    {
      if(s)
      {
        m=localtime(&t);
        strftime(otm,100,"%y/%m/%d %H:%M:%S",m);
        printf("%s\n",otm);
      }
      else
        printf("%s",ctime(&t));
    }
  }
}

void usage(s)
char *s;
{
  printf("Usage : %s [-diff] [-chr] <time>\n",s);
  printf(" where:\n");
  printf(" -diff ... print difference in hours between now and then\n");
  printf(" -chr ... time is in char format (as in \"date\" command)\n");
  printf(" else is in seconds-since-00:00:00,1/1/1970.\n");
}

long chr2tim(s)
char *s;
{
  struct tm tm;
  int i,j,y,c,p;
  long t;

  tm.tm_wday = -1;
  tm.tm_yday = -1;
  tm.tm_isdst = 0;
  tm.tm_zone = NULL;
  tm.tm_gmtoff = 0;

  if(s[10] == ' ')
    j=10;
  else
    j=9;
  i = ((10*'0')+'0');
  tm.tm_sec = ((s[j+7])*10)+s[j+8]-i;
  tm.tm_min = ((s[j+4])*10)+s[j+5]-i;
  tm.tm_hour = ((s[j+1])*10)+s[j+2]-i;
  if(s[8] != ' ')
  {
    if(s[9] != ' ')
    {
      tm.tm_mday = ((s[8])*10)+s[9]-i;
    }
    else
    {
      tm.tm_mday = s[8]-'0';
    }
  }
  else
  {
    tm.tm_mday = s[9]-'0';
  }
  
  if((s[j+10]>='0') && (s[j+10]<='9'))
    p=j+10;
  else
    p=j+14;
  y = ((s[p+2])*10)+s[p+3]-i;
  c = ((s[p])*10)+s[p+1]-i;
  tm.tm_year = ((c*100)+y)-1900;
  switch(s[4])
  {
  case 'J':
    if(s[5] == 'a')
      tm.tm_mon=0;
    else if(s[6] == 'n')
      tm.tm_mon=5;
    else
      tm.tm_mon=6;
    break;
  case 'F':
    tm.tm_mon=1;
    break;
  case 'M':
    if(s[6] == 'r')
      tm.tm_mon=2;
    else
      tm.tm_mon=4;
    break;
  case 'A':
    if(s[6] == 'r')
      tm.tm_mon=3;
    else
      tm.tm_mon=7;
    break;
  case 'S':
    tm.tm_mon=8;
    break;
  case 'O':
    tm.tm_mon=9;
    break;
  case 'N':
    tm.tm_mon=10;
    break;
  case 'D':
    tm.tm_mon=11;
    break;
  default:
    printf("I don't understand date \"%s\"\n",s);
    break;
  }

  t=timelocal(&tm);

  return(t);
}

===============================================================================
From: bern@TI.Uni-Trier.DE (Jochen Bern)

#!/bin/csh
#
if ( "$1" == "" ) then
        echo "Usage: `basename $0` <Time>"
        echo "where <Time> is in Seconds since 01-Jan-1970 00:00:00"
        exit 0
endif
@ HOUR = ( $1 % 86400 ) / 3600
@ MINUTE = ( $1 % 3600 ) / 60
echo "That's ${HOUR}:${MINUTE}."

===============================================================================
From: pallan@clare.risley.aeat.co.uk (Peter (jaffa cake) Allan)

This ought to do it.

:
# takes arg(s) of times in seconds
# eg ctime 801312638
# prints hh:mm:ss
# NO allowance for daylight-saving
#
echo $* | nawk '{
for(i=1;i <= NF;i++){
#
# mod of 24 hour day
j = $i % 86400
#print i,$i,j
h = int ( j / 3600)
m = int ( (j % 3600)/60)
s = int (j % 60)

printf("%02d:%02d:%02d\n",h,m,s)
}
}'

===============================================================================
From: raoul@MIT.EDU

Take a look in the gnu binutils source code, at
aeneas.mit.edu:/pub/gnu/binutils-*.tar.gz

===============================================================================
From: Jimi Xenidis <jimix@resunix.ri.sickkids.on.ca>

there is a program that comes with INN called convdate(1) that will do
what you need. If you want I can mail you the source.

===============================================================================
From: tim@ben.dciem.dnd.ca

Included below is the source and executable for a program which will takes
the large integer (in ASCII format) on stdin and pumps out the "HH:MM"
for that time.

#include <sys/types.h>
#include <time.h>

#define DEFAULT_FORMAT "%H:%M"

main(argc, argv)
char **argv;
{
        time_t raw_time;
        int nc;
        struct tm *t;
        char buf[128];
        char *fmt;

        if (argc > 1)
                fmt = argv[1];
        else
                fmt= DEFAULT_FORMAT;

        while(scanf("%d", &raw_time) == 1)
        {
                t = localtime(&raw_time);

                if ((nc = strftime(buf, sizeof(buf), fmt, t)) > 0)
                {
                        write(1, buf, nc);
                        write(1, "\n", 1);
                }
        }
}

[executable deleted for brevity, again]

===============================================================================
From: dwillard@scires.com
     
       When you say you want the hour:minute, do you mean the actual time
     of day, or the hours & minutes "since Jan. 1, 1970"? If it's the
     first, the "date" command can be used to format the date/time to
     almost what ever you want. For your example `date +%H:%M` will give
     it to you, if you stand a 24-hour clock....
     
     If it's something else you want, it's not too difficult to write your
     own utility that you can then use in your shell scripts. The C
     functions time(), localtime(), and strftime() should get you there.
     strftime() has many more formatting options than the "date" command,
     although you have to be careful; some of the options in Sun's version
     aren't portable to other Unix versions.
     
     Now, if it's just raw hours and minutes since the start of time
     (1/1/70? I was around before then...), you'll have to do a little math
     with the raw value that time() returns, remembering that you'll have
     to adjust for your timezone.
     
     Sorry I don't have a ready made utility for you...perhaps if you tell
     me exactly what you need I could whip up a quick C program in a day or
     so... :) But I'm sure someone else out there may have something
     already.
     
     Good Luck!
     
     David Willard

===============================================================================
From: FV Admin mail <fvadmin@sgf.fv.com>

GNU's "date" program will do what you're looking for. It's much like the
usual "date" program, except that you can tell it what date to assume is
"right now" and you can have it print out the epoch-seconds (in case you
want to go the other way).

===============================================================================
From: "Marcus Pless" <mpless@ljswc.UCSD.EDU>

The "date" command is quite capable of generating human
readable output.

On a machine running
        SunOS servo 4.1.3_U1 1 sun4m

using csh I can do the following:

[servo]: set time=`date +%H:%M:%S`
0.0u 0.0s 0:00 500% 0+96k 0+0io 0pf+0w
[servo]: echo $time
08:15:47

I use this in shell scripts quite frequently for time/day/date stamps.
In a script using sh the following sets up temporary log files with
filenames containing the day and time:

day=`date +%a`
time=`date +%H:%M:%S`
log=/tmp/ping.log.$day.$time
errs=/tmp/pingerr.$day.$time

Hope this helps.

===============================================================================
From: jayl@lattice.com (Jay Lessert)

Perl answer:

#! /usr/local/bin/perl
# convert single integer on command line (assumed to be standard
# unix "seconds since 1/1/70" time) to local date.

require "ctime.pl";

if ($#ARGV >= 0) {
    $time = shift(@ARGV);
    }
else {
    die "Usage: num2date number\n";
}

print &ctime($time);

C answer:

/* convert single integer on command line (assumed to be standard
 * unix "seconds since 1/1/70" time) to local date.
 */
#include <stdio.h>
#include <time.h>

int main(argc, argv)
int argc;
char **argv;
{
    int flag;
    time_t start;
    time_t *startp;
    startp = &start;
    /* get arguments */
    if (argc == 1) {
        printf("Usage: num2date number\n");
        exit(1);
    }
    start = (time_t) atoi(*++argv);
    printf("Time is: %i\n", start);
    printf("Date is: %s", ctime(startp));
}

===============================================================================
From: guy@netapp.com (Guy Harris)

I don't know of any, other than this one, which I whipped up at one
point for a reason I no longer remember; it takes, as a command-line
argument, a number (decimal by default, hex if it begins with "0x",
octal if it begins with "0"), treats it as a "time_t", and prints out
the local time for that "time_t":

#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: ctime.c
# Wrapped by guy@nova on Wed May 24 10:53:01 1995
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ctime.c' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'ctime.c'\"
else
echo shar: Extracting \"'ctime.c'\" \(426 characters\)
sed "s/^X//" >'ctime.c' <<'END_OF_FILE'
X#include <stdio.h>
X
X#include <time.h>
X
Xextern long strtol();
X
Xint
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X char *p;
X time_t then;
X
X if (argc != 2) {
X (void) fprintf(stderr, "Usage: ctime <time_t value>\n");
X return 1;
X }
X
X then = strtol(argv[1], &p, 0);
X if (p == argv[1] || *p != '\0') {
X (void) fprintf(stderr, "ctime: Bad time_t value %s\n",
X argv[1]);
X return 1;
X }
X
X printf("%s", ctime(&then));
X return 0;
X}
END_OF_FILE
if test 426 -ne `wc -c <'ctime.c'`; then
    echo shar: \"'ctime.c'\" unpacked with wrong size!
fi
# end of 'ctime.c'
fi
echo shar: End of shell archive.
exit 0

===============================================================================
From: Jeff Victor <victoj@kellas.Sage.EDU>

If you change your mind, I wrote a C program to do this.

===============================================================================
From: etnibsd!vsh@uunet.uu.net (Steve Harris)

If perl is installed:

    perl -e 'print time, "\n";'

===============================================================================
From: Markus Buchhorn <markus@octavia.anu.edu.au>

If you use perl, that has builtin calls to do this. Otherwise just use
the following C code (compile it, and run it as 'secs2date <n>':

#include <time.h>
long int secs;
time_t *clock;
void main(int argc, char *argv[])
{
secs = atol(argv[1]);
clock = &secs;
printf("ctime() = %s",ctime(clock));
}

e.g.
% secs2date 800000000
ctime() = Tue May 9 16:13:20 1995

I also have the inverse code if you want that as well.

===============================================================================
From: kevin@anymore.more.com (Kevin Sheehan {Consulting Poster Child})

main(int argc, char **argv) { printf("%s", ctime(atoi(argv[1]))) ; }

will take one timestamp and print the date format...



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:10:26 CDT