Need to minus one day from a date given

Hello Folks,

I have a variable output holding date as below -
output = "20141220"
I need to extract a day out of it and store it in another variable i.e. something similar to below -
output1=20141219"
and if the month is changing i.e. date in on 31st or 1st it should be taken care of
"date -d" is not supported in the version I am using, any leads will be greatly appreciated...

You don't need date -d for this type of things - use the TZ-variable (Time Zone) instead.

You see, time ist stored in "UTC" (universal time coordinated) in UNIX systems. the local time is just an offset from this, and this offset is set by the TZ variable, which you can change for a single command, for instance:

# TZ=GMT+1 date
Mon Jul  3 08:40:29 GMT 2017
# TZ=GMT+25 date
Sun Jul  2 08:40:37 GMT 2017

You see, adding/subtracting 24 to the TZ variable changes the output by 24 hours - which is a day. The same way you can get any arbitrary date, even in the future:

# TZ=GMT+1 date
Mon Jul  3 08:43:32 GMT 2017
# TZ=GMT+25 date
Sun Jul  2 08:43:32 GMT 2017
# TZ=GMT-23 date
Tue Jul  4 08:43:32 GMT 2017

I hope this helps.

bakunin

Thank you for the solution, but I do not deal with system date, it is an arbitary date given by the system and I need to minus a day from it.

Hi.

If you can use ksh93, then there is extensive support for date manipulation.

See Korn Shell 93 Date Manipulation « Musings for a number of examples ... cheers, drl

You could use perl

save this as dayadd.pl:

#! /usr/bin/env perl
use Time::Local;
use POSIX qw(strftime);

 my ($yy, $mm, $dd) = unpack "A4A2A2", $ARGV[0];
 eval { print strftime("%Y%m%d\n", localtime(timelocal(0,0,0,$dd,$mm - 1,$yy) + $ARGV[1]*24*60*60)) } ;
 exit 1 if $@ ;
 exit 0;

Then you can use it like this:

$ ./dayadd.pl 20141220 -1 || echo "Invalid date!"
20141219

$ ./dayadd.pl 20132202 -1 || echo "Invalid date"
Invalid date
1 Like

This is how you do it in Solaris.

:~$ gdate +%Y%m%d
20170705

:~$ gdate +%Y%m%d -d "-10days"
20170625

here's --help from the util. FYI gdate and date are NOT the same thing.

 gdate --help
Usage: gdate [OPTION]... [+FORMAT]
  or:  gdate [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
Display the current time in the given FORMAT, or set the system date.

  -d, --date=STRING         display time described by STRING, not 'now'
  -f, --file=DATEFILE       like --date once for each line of DATEFILE
  -I[TIMESPEC], --iso-8601[=TIMESPEC]  output date/time in ISO 8601 format.
                            TIMESPEC='date' for date only (the default),
                            'hours', 'minutes', 'seconds', or 'ns' for date
                            and time to the indicated precision.
  -r, --reference=FILE      display the last modification time of FILE
  -R, --rfc-2822            output date and time in RFC 2822 format.
                            Example: Mon, 07 Aug 2006 12:34:56 -0600
      --rfc-3339=TIMESPEC   output date and time in RFC 3339 format.
                            TIMESPEC='date', 'seconds', or 'ns' for
                            date and time to the indicated precision.
                            Date and time components are separated by
                            a single space: 2006-08-07 12:34:56-06:00
  -s, --set=STRING          set time described by STRING
  -u, --utc, --universal    print or set Coordinated Universal Time
      --help     display this help and exit
      --version  output version information and exit

FORMAT controls the output.  Interpreted sequences are:

  %%   a literal %
  %a   locale's abbreviated weekday name (e.g., Sun)
  %A   locale's full weekday name (e.g., Sunday)
  %b   locale's abbreviated month name (e.g., Jan)
  %B   locale's full month name (e.g., January)
  %c   locale's date and time (e.g., Thu Mar  3 23:05:25 2005)
  %C   century; like %Y, except omit last two digits (e.g., 20)
  %d   day of month (e.g., 01)
  %D   date; same as %m/%d/%y
  %e   day of month, space padded; same as %_d
  %F   full date; same as %Y-%m-%d
  %g   last two digits of year of ISO week number (see %G)
  %G   year of ISO week number (see %V); normally useful only with %V
  %h   same as %b
  %H   hour (00..23)
  %I   hour (01..12)
  %j   day of year (001..366)
  %k   hour, space padded ( 0..23); same as %_H
  %l   hour, space padded ( 1..12); same as %_I
  %m   month (01..12)
  %M   minute (00..59)
  %n   a newline
  %N   nanoseconds (000000000..999999999)
  %p   locale's equivalent of either AM or PM; blank if not known
  %P   like %p, but lower case
  %r   locale's 12-hour clock time (e.g., 11:11:04 PM)
  %R   24-hour hour and minute; same as %H:%M
  %s   seconds since 1970-01-01 00:00:00 UTC
  %S   second (00..60)
  %t   a tab
  %T   time; same as %H:%M:%S
  %u   day of week (1..7); 1 is Monday
  %U   week number of year, with Sunday as first day of week (00..53)
  %V   ISO week number, with Monday as first day of week (01..53)
  %w   day of week (0..6); 0 is Sunday
  %W   week number of year, with Monday as first day of week (00..53)
  %x   locale's date representation (e.g., 12/31/99)
  %X   locale's time representation (e.g., 23:13:48)
  %y   last two digits of year (00..99)
  %Y   year
  %z   +hhmm numeric time zone (e.g., -0400)
  %:z  +hh:mm numeric time zone (e.g., -04:00)
  %::z  +hh:mm:ss numeric time zone (e.g., -04:00:00)
  %:::z  numeric time zone with : to necessary precision (e.g., -04, +05:30)
  %Z   alphabetic time zone abbreviation (e.g., EDT)

By default, date pads numeric fields with zeroes.
The following optional flags may follow '%':

  -  (hyphen) do not pad the field
  _  (underscore) pad with spaces
  0  (zero) pad with zeros
  ^  use upper case if possible
  #  use opposite case if possible

After any flags comes an optional field width, as a decimal number;
then an optional modifier, which is either
E to use the locale's alternate representations if available, or
O to use the locale's alternate numeric symbols if available.

Examples:
Convert seconds since the epoch (1970-01-01 UTC) to a date
  $ date --date='@2147483647'

Show the time on the west coast of the US (use tzselect(1) to find TZ)
  $ TZ='America/Los_Angeles' date

Show the local time for 9AM next Friday on the west coast of the US
  $ date --date='TZ="America/Los_Angeles" 09:00 next Fri'

Report gdate bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
Report gdate translation bugs to <http://translationproject.org/team/>
For complete documentation, run: info coreutils 'gdate invocation'