------------------------------------------------------------------------------- Date & Time Handling ------------------------------------------------------------------------------- Date-Time NOW IEEE date only date=`date -I` date=`date +%F` IEEE date_time date=`date +'%F_%T'` or for solaris 8 date=`date +'%Y-%m-%d_%T'` or for very old machines date=`date +'%Y-%m-%d_%R:%S'` date=`date +'%Y-%m-%d_%H:%M:%S'` For really old machines (SunOS)... While the newest UNIX's allow a %Y for a four digit year older machines like SunOS does NOT. This means the year will need to be extracted from the date output (or alternative format code). year=`date | sed 's/.*\([0-9][0-9][0-9][0-9]\).*/\1/'` date=`date $year-%m-%d_%H:%M:%S" *** BASH built-in printf date features (NOT on redhat 6) save to variable, and -1 means NOW a value of -2 is the time when the shell was started! printf -v date '%(%F_%T)T' -1 Other Date formats Examples IEEE date=`date +'%F_%T'` 2019-07-16_14:33:10 Stamp date "+%Y%m%d%a%H%M" 20190716Tue1433 timestamp date "+%Y%m%dt%H%M%S" 20190716t143321 If you have the MH mail system (NMH) install you can convert the date to rfc822 complient date format used by mail, using the "dp" program. This has its own output format codes. /usr/libexec/nmh/dp "`date`" or /usr/libexec/nmh/dp -format '%(year{text})' "`date`" or /usr/libexec/nmh/dp \ -format '%04(year{text})-%02(mon{text})-%02(mday{text})' \ "`date`" # some math maths... days_left=$(($(date +%j -d"Dec 31, $(date +%Y)")-$(date +%j))) echo "There are $days_left days left in year $(date +%Y)." ------------------------------------------------------------------------------- Your Time Zone Offset in Seconds. date +%s -d '1 Jan 1970' For GMT+10 (Australia) it's -36000 That is GMT is 36000 seconds behind this location. ASIDE: USA has a posivtive value as GMT is ahead of those time zones. ------------------------------------------------------------------------------- Date - Time in Seconds, NOW! (for later comparision) EG: getting the number of seconds since epoch (midnight, 1 Jan 1970, GMT) This is for the purposes of timing various command and comparing the start and end times. The problem is as there is no standard way for geting the system clock under normal plain shell scripts. Under linux (Gnu-date) you can date +%s BASH printf can save directly into variable (Not on redhat 6) printf -v now '%(%s)T' -1 printf 'now = %s => %(%F_%T)T\n' $now $now # => now = 1673845037 => 2023-01-16_14:57:17 With perl you can use... perl -e 'print time(), "\n"' Warning perl '-m' function returns time since program start! --- Seconds since year start (for short time deltas)... Do not rely on it for time deltas longer than a year (which is variable by a day), and there can be a schedualed leap second at times... date +'%j * 86400 + %H * 3600 + %M * 60 + %S' | bc NOTE: %j is day within the year, which takes into account unequal months and the leap day. ------------------------------------------------------------------------------- Seconds to Date.... Date date --date=@1000000000 +%F_%T 2001-09-09_11:46:40 BASH printf built-in, date formatter printf '%(%F_%T)T\n' 1000000000 2001-09-09_11:46:40 PERL... perl -e 'require "ctime.pl"; print &ctime(1000000000);' for more see the perl/general.hints page) ------------------------------------------------------------------------------- Date of Yesterday (without a lot of fuss) Getting yesterdays day is usually best done in either C or perl. #!/usr/bin/perl require "ctime.pl"; print &ctime($^T - 60*60*24); alternativally perl -MPOSIX -le '@now = localtime; $now[3] -= 1; print scalar localtime mktime @now' How about 14 months, 9 days and 7 seconds ago perl -MPOSIX -le '@now = localtime; $now[0] -= 7; $now[4] -= 14; $now[7] -= 9; print scalar localtime mktime @now' GNU date (linux) makes this very easy date -d yesterday +%F # <--- the perfect solution But it can do a lot more... date -d 'last week' date -d '-4 hours' date -d '1 month ago' date -d "today -1 days" +%Y-%m-%d even do some date maths, using specific dates date -d "2010-01-25 +10 days" +%F 2010-02-04 Or loop over a week week=2021/10/04 # start of week (monday) for (( i=0; i<7; i++ )); do day=$(date +%Y/%m/%d -d "$week + $i day") echo $day done Or list of dates, starting at a particular date... seq 0 30 | xargs -i date -d "2010-01-15 +{} days" +%F By changing your timezone you can fake the getting of yesterdays date, But ONLY if you live in Australia where it is already tomorrow!. It is not perfect (2 hours short but close enough in most cases) env TZ=GMT+12 date ------------------------------------------------------------------------------- Days in a month days_of_month() { # @params: #month #year m="$1"; y="$2"; a=$(( 30+(m+m/8)%2 )) (( m==2 )) && a=$((a-2)) (( m==2 && y%4==0 && ( y<100 || y%100>0 || y%400==0) )) && a=$((a+1)) printf '%d' $a } year=`date +%Y` month=`date +%m | sed -e 's/^0//'` days_in_this_month=$( days_of_month $month $year ) tmp_year=$(( $month==1 ? ($year-1):$year )) tmp_month=$(( $month==1 ? 12 : $month-1 )) days_in_last_month=$( days_of_month $tmp_month $tmp_year ) But GNU date allows date math making this easy... year=`date +%Y` month=`date +%m | sed -e 's/^0//'` days_in_this_month=$( date +%d -d '$year-$month-1 +1month -1day' ) days_in_last_month-$( (date +%d -d '$year-$month-1 -1day' ) ------------------------------------------------------------------------------- Date Sorting in Log files. Sorting logs with time like... [03/07/2013 08:18:45 AM] PikaPika01 logged in. [03/07/2013 08:19:55 AM (world: 975,86,2494)] PikaPika01: hey This has problems... 1/ The date order is American MM/DD/YYYY format 2/ AM and PM must be sorted before the actual time field 3/ "AM]" and "AM (.." word sort differently (ignore trailing chars) 4/ "12" is before "01" that is 12 AM is before 01 AM Here is my solution... cat file | sed 's/ 12:/ 00:/' | sort -t\ -k1.8,1.11 -k1.2,1.3 -k1.4,1.5 -k3,3.2 -k2,2 -k4 | sed 's/ 00:/ 12:/' >merged.log Note the '12' is modified to '00' for the sort, then converted back ---- Alternative... Convert to and from Seconds since Epoch ------------------------------------------------------------------------------- Humanized Time Delta # This is a BASH script, for time deltas of less than a month. # # For deltas (rough and exact) of periods greater than a month, # see "info/perl/general.txt" with uses the 'Data::Calc' module humanized_delta_time() { secs=$((`date +%s` - start)) days=$(($secs/86400)) secs=$((secs%86400)) hours=$((secs/3600)) secs=$((secs%3600)) mins=$((secs/60)) secs=$((secs%60)) if (( $days > 0 )); then #delta="${days}d ${hours}h" delta=`printf "%d days %d:%02d" $days $hours $mins` elif (( $hours > 0 )); then #delta="${hours}h ${mins}m" delta=`printf "%d:%02d:%02d" $hours $mins $secs` elif (( $mins > 0 )); then #delta="${mins}m ${secs}s" delta="$mins mins $secs secs" elif (( secs > 0 )); then #delta=`printf "%d:%02d:%02d" $hours $mins $secs` #delta="only $secs seconds" delta="$secs secs" else delta="---" # zero delta fi echo $delta } #start=$(date +%s) printf -v start '%(%s)T' -1 # start time in seconds #... do something ... #end=$(date +%s) printf -v end '%(%s)T' -1 # end time in seconds delta=$(humanized_delta_time (( end - start))) echo "Time Delta $delta" -------------------------------------------------------------------------------