#!/usr/bin/perl -w # +-======-+ # Copyright (c) 2003-2018 United States Government as represented by # the Admistrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, # REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN # COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT AS # REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT AGENCY"). # THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT AGENCY, IS AN # INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT DISTRIBUTIONS OR # REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO USES, REPRODUCES, # DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED # HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, ACCEPTING IN FULL THE # RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT. # # Government Agency: National Aeronautics and Space Administration # Government Agency Original Software Designation: GSC-15354-1 # Government Agency Original Software Title: GEOS-5 GCM Modeling Software # User Registration Requested. Please Visit http://opensource.gsfc.nasa.gov # Government Agency Point of Contact for Original Software: # Dale Hithon, SRA Assistant, (301) 286-2691 # # +-======-+ # # Simple perl script for ticking the clock. # # !Revision History # 2000Apr04 daSilva Initial version # 2010Sep17 Stassi Replaced Time::Local routines with sub add_seconds() # so that script will work beyond 19Jan2038 #------------------------------------------------------------------ use strict; # global variables #----------------- my $SECS_PER_MIN = 60; my $MINS_PER_HOUR = 60; my $HOURS_PER_DAY = 24; my $MONTHS_PER_YR = 12; my $SECS_PER_HOUR = $SECS_PER_MIN * $MINS_PER_HOUR; my $SECS_PER_DAY = $SECS_PER_HOUR * $HOURS_PER_DAY; my $MINS_PER_DAY = $MINS_PER_HOUR * $HOURS_PER_DAY; # generic MONTH and YEAR definitions #----------------------------------- my $DAYS_PER_MONTH = 30; my $DAYS_PER_YEAR = 365; my %lastday = (1 => 31, 2 => 0, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31); # main program #------------- { my ($numargs, $nymd, $nhms, $isecs); my ($iymd, $ihms, $hh, $mm, $ss); my ($yr, $mnth, $dy, $idays); $numargs = scalar @ARGV; usage() if $numargs < 1 or $numargs > 4; $nymd = shift @ARGV; $nhms = shift @ARGV; if ($numargs == 3) { $isecs = shift @ARGV; } elsif ($numargs == 4) { $iymd = shift @ARGV; $ihms = shift @ARGV; ($hh, $mm, $ss) = parseIntTime($ihms); ($yr, $mnth, $dy) = parseIntTime($iymd); $idays = $dy + $mnth*$DAYS_PER_MONTH + $yr*$DAYS_PER_YEAR; $isecs = $ss; $isecs += $SECS_PER_MIN * $mm; $isecs += $SECS_PER_HOUR * $hh; $isecs += $SECS_PER_DAY * $idays; } $isecs = 86400 unless defined($isecs); $nhms = 0 unless $nhms; ($nymd, $nhms) = add_seconds($nymd, $nhms, $isecs); if ( $numargs == 1 ) { print "$nymd\n" } else { print "$nymd $nhms\n" } } #................................................................... sub parseIntTime { my ($hhmmss, $hh, $mm, $ss, $sign); $hhmmss = shift @_; $sign = 1; if ($hhmmss < 0) { $sign = -1; $hhmmss *= -1 } $hh = $sign * ( int($hhmmss / 10000) ); $mm = $sign * ( int($hhmmss % 10000 / 100) ); $ss = $sign * ( $hhmmss % 100 ); return ($hh, $mm, $ss); } #................................................................... sub add_seconds { my ($nymd, $nhms, $isecs); my ($yr, $mnth, $dy, $hh, $mm, $ss); $nymd = shift @_; $nhms = shift @_; $isecs = shift @_; ($yr, $mnth, $dy) = parseIntTime($nymd); ($hh, $mm, $ss) = parseIntTime($nhms); # check validity of initial date/time #------------------------------------ die "Error; invalid month ($mnth) in initial date: $nymd;" if $mnth < 1 or $mnth > 12; die "Error; invalid day ($dy) in initial date: $nymd;" if $dy < 1 or $dy > num_days_in_month($yr, $mnth); die "Error; invalid hour ($hh) in initial time: $nhms;" if $hh < 0 or $hh >= $HOURS_PER_DAY; die "Error; invalid minute ($mm) in initial time: $nhms;" if $mm < 0 or $mm >= $MINS_PER_HOUR; die "Error; invalid seconds ($ss) in initial time: $nhms;" if $ss < 0 or $ss >= $SECS_PER_MIN; # adjust seconds #--------------- return ($nymd, $nhms) unless $isecs; $ss += $isecs; while ($ss <= -1*$SECS_PER_DAY) { $ss += $SECS_PER_DAY; $dy-- } while ($ss <= -1*$SECS_PER_HOUR) { $ss += $SECS_PER_HOUR; $hh-- } while ($ss < 0 ) { $ss += $SECS_PER_MIN; $mm-- } while ($ss >= $SECS_PER_DAY) { $ss -= $SECS_PER_DAY; $dy++ } while ($ss >= $SECS_PER_HOUR) { $ss -= $SECS_PER_HOUR; $hh++ } while ($ss >= $SECS_PER_MIN) { $ss -= $SECS_PER_MIN; $mm++ } # adjust minutes #--------------- while ($mm < 0) { $mm += $MINS_PER_HOUR; $hh-- } while ($mm >= $MINS_PER_HOUR) { $mm -= $MINS_PER_HOUR; $hh++ } # adjust hours #------------- while ($hh < 0) { $hh += $HOURS_PER_DAY; $dy-- } while ($hh >= $HOURS_PER_DAY) { $hh -= $HOURS_PER_DAY; $dy++ } # adjust days, months, and years #------------------------------- while ($dy < 1) { $mnth--; while ($mnth < 1) { $mnth += $MONTHS_PER_YR; $yr-- } $dy += num_days_in_month($yr, $mnth); } while ($dy > num_days_in_month($yr, $mnth)) { $dy -= num_days_in_month($yr, $mnth); $mnth++; while ($mnth > $MONTHS_PER_YR) { $mnth -= $MONTHS_PER_YR; $yr++ } } # zero-fill values where necessary for 2-digit and 4-digit representation #------------------------------------------------------------------------ foreach (\$ss, \$mm, \$hh, \$dy, \$mnth) { $$_ = sprintf "%02i", $$_ } $yr = sprintf "%04i", $yr; return "$yr$mnth$dy", "$hh$mm$ss"; } #................................................................... sub num_days_in_month { my ($yr, $mnth); $yr = shift @_; $mnth = shift @_; # special handling for month of February #--------------------------------------- if ($mnth == 2) { $lastday{2} = 28; $lastday{2} = 29 if $yr%4==0 and ($yr%100!=0 or $yr%400==0); } return $lastday{$mnth}; } #................................................................... sub usage { print <<"EOF"; NAME tick - Increments date and time SYNOPSIS tick yyyymmdd tick yyyymmdd hhmmss tick yyyymmdd hhmmss isecs tick yyyymmdd hhmmss iyymmdd ihhmmss where yyyymmdd = 8-digit initial date hhmmss = 6-digit initial time isecs = number of seconds to add to initial date/time iyymmdd = date increment to add to initial date/time ihhmmss = time increment to add to initial date/time DESCRIPTION Increments initial date/time (yyyymmdd/hhmmss) by isecs seconds, where isecs is specified directly as an integer number of seconds or indirectly as a time increment given by iyymmdd and ihms. NOTES 1. Using the date increment to add months and years is not recommended since this will increment by generic 30-day months and 365-day years 2. hhmmss defaults to 000000 if not specified. 3. isecs defaults to 86400 (one day) if neither isecs nor iyymmdd and ihms are specified. EXAMPLES tick 20000228 ===> 20000229 tick 19990930 120000 ===> 19991001 120000 tick 19990930 060000 36000 ===> 19990930 160000 tick 19990930 060000 -36000 ===> 19990929 200000 tick 19990930 060000 5 0 ===> 19991005 060000 tick 19990930 060000 -5 0 ===> 19990925 060000 tick 19990930 060000 5 030000 ===> 19991005 090000 tick 19990930 060000 0 -120000 ===> 19990929 180000 AUTHOR Arlindo da Silva, dasilva\@dao.gsfc.nasa.gov EOF exit(1); }