SUMMARY: time routine

From: Vince Hickey (hickey@nrlmry.navy.mil)
Date: Tue Mar 31 1998 - 11:52:05 CST


On Mon, Mar 30, 1998 at 06:55:50PM -0800, Vince Hickey wrote:
> Anyone have a sh or csh routine that gives the time since "day 1". ie
> 00:00:00 UTC, January 1, 1970.

Thanks to everyone who sent me an answer! I got a lot of insight to the
time issue... For me the simpliest solution was From: seeger@cise.ufl.edu
(Charles Seeger) made a /bin/sh script using the standard date command.
This solution insures portability and does not require compiling or
installation of additional utilites.

I did not try all the solutions though each have their merits! The C code
is fast, the perl code is simple, and the sh code is portable.

Outstanding sun-mgrs!

Vince

--- the solution I implemented ---

You could just use one date command, too:

set -- `date -u '+%Y %j %H %M %S'`
UEPOCH_DAYS=`expr 365 \* \( $1 - 1970 \) + \( $1 - 1969 \) / 4 + $2 - 1`
MINS=`expr 60 \* $3 + $4`
SECS=`expr 3600 \* $3 + 60 \* $4 + $5`
UEPOCH_MINS=`expr 1440 \* $UEPOCH_DAYS + $MINS`
UEPOCH_SECS=`expr 86400 \* $UEPOCH_DAYS + $SECS`

If you are calculating seconds, you may want to use dc rather than expr,
in order to avoid overflows.

And, of course, this won't really be accurate to the second. If your
application needs real accuracy, you may need to look at NTP or radio
clocks and a more direct time query (perl or C). If you want to get
started into the arcania of timekeeping, the NTP home page is the
best place to go: http://www.eecis.udel.edu/~ntp.

---------------------------------------------------------------------------

!!!!!! Other code below !!!!!!

---------------------------------------------------------------------------

From: Jeff Wasilko <jeffw@smoe.org>

Perl can do it easily (using time).

GNU date can do it as well:

shell2% /usr/local/bin/date +%s
891315483

---------------------------------------------------------------------------
---------------------------------------------------------------------------
From: seeger@cise.ufl.edu (Charles Seeger)

This is what I use for Solaris "last change" shadow fields:

In sh:

# Calculate number of days since the Unix time origin (1 Jan 1970)
# Leap years are offset from 1972, but subtract one year, since `date +%j`
# should account for leap days in the current year.
# Only count full days, so decrement by one to truncate off the partial day.
# Years divisible by 100 are not leap years unless they are divisible by 400.
# So, 2000 *is* a leap year and will be handled correctly by this formula.
# XXX This calculation with fail for all years after 2100, not inclusive.

set `date -u '+%Y %j'`
LASTCHG=`expr 365 \* \( $1 - 1970 \) + \( $1 - 1969 \) / 4 + $2 - 1`

Of course, it is even easier in perl:

$LastChange = int( time() / (24*3600) );

---------------------------------------------------------------------------

From: seeger@cise.ufl.edu (Charles Seeger)

In sh you could multiply $LASTCHG by either 1440 or 86400 and then add
either
        set -- `date -u '%H %M'`
        MINS=`expr 60 \* $1 + $2`
or
        set -- `date -u '%H %M %S'`
        SECS=`expr 3600 \* $1 + 60 \* $2 + $3`

WARNING: that's untested code.

You could just use one date command, too:

set -- `date -u '+%Y %j %H %M %S'`
UEPOCH_DAYS=`expr 365 \* \( $1 - 1970 \) + \( $1 - 1969 \) / 4 + $2 - 1`
MINS=`expr 60 \* $3 + $4`
SECS=`expr 3600 \* $3 + 60 \* $4 + $5`
UEPOCH_MINS=`expr 1440 \* $UEPOCH_DAYS + $MINS`
UEPOCH_SECS=`expr 86400 \* $UEPOCH_DAYS + $SECS`

If you are calculating seconds, you may want to use dc rather than expr,
in order to avoid overflows.

And, of course, this won't really be accurate to the second. If your
application needs real accuracy, you may need to look at NTP or radio
clocks and a more direct time query (perl or C). If you want to get
started into the arcania of timekeeping, the NTP home page is the
best place to go: http://www.eecis.udel.edu/~ntp.

---------------------------------------------------------------------------
---------------------------------------------------------------------------

From: "Robert G. Ferrell" <rferrell@usgs.gov>

#!/usr/local/bin/perl
# Script to convert seconds-since-epoch to current date
# Written 11/28/97 RGF
# Revised 1/12/98 RGF To put output in UNIX DATE format
# Version 1.1

$sse = $ARGV[0];
$days = 0;
$hours = 0;
$mins = 0;
$secs = 0;
$year = 0;
$month = "";

if ($sse eq "-v") {
  print "This is sec2date, version 1.1, 1/12/98\n";
  exit;
}

unless ($sse) {
  print "Usage: sec2date seconds\n";
  exit;
  }

&days;
&year;
&month;
&date;
&weekday;
&hours;
&mins;
&secs;
&print;

sub days {

$day_r = $sse / 86400;
  if ($day_r < 1) {
    $day_i = 0;
  } else {
    $day_i = int ($day_r);
  }
$days = $day_i;
}

sub year {

    if ($days <= 789) { $leap = 0;
    } elsif ($days <= 2249) { $leap = 1;
    } else {
        $leap = int ((($days - 2250) / 1460) + 1);
    }
    $years_r = ($day_r - $leap) / 365 ;
    $years_i = int ($years_r);
    $year = $years_i + 1970;
        if ($year % 4 == 0) {
            $leap_n = 1;
        } else { $leap_n = 0;
        }
}

sub month {

   $months_r = $years_r - $years_i;
   $months_l = $months_r * 12;
   $months_i = int ($months_l);
     if ($months_i == 0) {
       $m_a = 0;
       $m_a = $months_i;
     } else { $m_a = $months_i; }

   @month = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec");
   $month = $month[$m_a];
}

sub date {

   if (($m_a == 3) || ($m_a == 5) || ($m_a == 8) || ($m_a == 10)) {
       $days_mon = 30;
   } elsif (($m_a == 1) && ($leap_n == 1)) {
       $days_mon = 29;
   } elsif (($m_a == 1) && ($leap_n == 0)) {
       $days_mon = 28;
   } else { $days_mon = 31; }
   $date_r = $months_l - $months_i;
   $date = (int ($date_r * $days_mon)) + 1;
   if ($date == 0) { $date = 1; }
}

sub weekday {

    $wday_r = $days % 7;
    @wday = ("Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed");
    $wday = $wday[$wday_r];
}

sub hours {

$day_l = abs (($day_r - $day_i) * 24);
$hour_r = $day_l;
 if ($hour_r < 1) {
    $hour_i = 0;
  } else {
    $hour_i = int ($hour_r);
  }
$hours = $hour_i;
}

sub mins {

$hour_l = abs (($hour_r - $hour_i) * 60);
$min_r = $hour_l;
 if ($min_r < 1) {
    $min_i = 0;
  } else {
    $min_i = int ($min_r);
  }
$mins = $min_i;
}

sub secs {

$min_l = abs (($min_r - $min_i) * 60);
$sec_r = $min_l;
$sec_i = int ($sec_r);
$sec_l = $sec_r - $sec_i;
$secs = $sec_i;
  if ($sec_l >= 0.5) { $secs++; }
}

sub print {
print "Your time was $days days, $hours hours, $mins minutes, and $secs
seconds since the beginning of the epoch.\n";

if ($hours < 10) { $hours = "0" . $hours; }
if ($mins < 10) { $mins = "0" . $mins; }
if ($secs < 10) { $secs = "0" . $secs; }

$full_date = ("$wday $month $date $hours:$mins:$secs $year");

print "This corresponds to $full_date.\n";
}

---------------------------------------------------------------------------
---------------------------------------------------------------------------

From: Mark Bergman <bergman@phri.nyu.edu>

-----------------------------------------------------------------
#! /usr/bin/perl
require "ctime.pl"; # For date calculations.
$daylength=86400; # # of seconds in a day
$now=time();
$days=$now/$daylength;
$days=~s/\.[0-9]+//;

$verbose=&ctime($now);
chop($verbose);
print "It is now \"$verbose\", $days days since the epoch.\n";
-----------------------------------------------------------------

Or, in C:

-----------------------------------------------------------------
/* epoch.c return the number of days since the epoch--Jan 1, 1970 */

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

main()
{

        long daylength=86400; /* # of seconds in a day */
        long days,secs,time();

        secs=time(0);

        days=secs/daylength;
        printf("%ld\n",days);
        exit(0);
}

---------------------------------------------------------------------------
---------------------------------------------------------------------------

From: Dimitris Evmorfopoulos <devmorfo@hol.net>

Just compile the C program below and have it in your /usr/bin It gives days
since 1/1/1970 since I used it for shadow expiration checks but then with minor
modifications it can give seconds just like time. (remove the
multiplications and divisions by 86400) With on args it gives current day or
with a day argument gives the corresponding date. No checks done here.

-- begin include --

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

main(int argc, char *argv[]) {
  time_t t;
  char str[1024];
  int i;

  if (argc == 2) {
    t = atoi(argv[1]) * 86400;
    sprintf(str, "%s", ctime(&t));
    if (str[strlen(str)-1] == '\n') str[strlen(str)-1] = 0;
    for (i=0;i<6;i++) str[10+i] = str[19+i];
    printf("%s\n",str);
    }
  else {
    t = time(NULL);
    printf("%d\n",(int)t/86400);
    }

  }

-- end include --

---------------------------------------------------------------------------

--

---------------------------------------------------------------------- o | Vince Hickey, Stickman Administrator <|> | Network Engineer, System Administration / \ | "Creation is an act of sheer will." | - John Hammond (Jurrasic Park) ---------------------------------------------------------------------- Naval Research Lab at Monterey hickey@nrlmry.navy.mil 7 Grace Hopper Ave MS#2 voice: 408 656 3530 Monterey, CA 93943-5502 fax: 408 656 4769 ----------------------------------------------------------------------



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:12:35 CDT