Convert a date in Shell - shell

This is a hart one, how do I convert a date like
12-23-11 13:37
In something like(seconds should always be 00)
Fri Dec 23 13:18:58 CET 2011
?

With gnu date 5.97, you can do:
$ date -d '11-12-23 13:37'
to get what you want, so all you need to do is massage your input.
Since gnu date is not ubiquitous, here's a quick perl script that does what you want:
$ echo 12-23-11 13:37 |
perl -MTime::Local -wnE '
y/-:/ /;
#F=split;
say scalar localtime timelocal( 0, $F[4], $F[3], $F[1], $F[0] - 1,$F[2]);
'
Fri Dec 23 13:37:00 2011
(Requires perl 5.10 for -E and say, but should work in older perl using -e and print.)

If this is a script for yourself and not something that will have to run in a million different environments, then depending on what version of date you have available, you should be able to use it.
Read the man page for your particular version of date. For example, if it's the version documented at http://ss64.com/bash/date.html, you can use --date for the input string, etc.
On Mac OS X, use the -f option to specify the input format, the -j option so that it doesn't try to set the date, and with specifying the output format on the command line.

Related

How I can format a date in shell

I want to convert a custom date format DD-%%%-YYYY to a standard one: YYYYMMDD
Possible values of %%% are:
Jan Fev Mar Avr Mai Jun Jui Aou Sep Oct Nov Dec
Assuming the input is a bash variable, how do I transform it to the standard format?
Example:
$ fr_date='09-Aou-2018'
$ # [transformation]
# sql_date should now contain 20180809
$ echo "$sql_date"
20180809
You can use the date utility.
fr_date='09-Aug-2018'
sql_date="$(date --date=$fr_date +%Y%m%d)"
echo $sql_date
20180809
Please also refer to the date man page for more information.
Additionally, date does not support custom locales, format must be locale independent. Try to store dates as simple Unix epoch.
Solution 1: Rewrite the french months into english, then use date to read and format it:
Pure bash:
tmp=${fr_date/Fev/Feb} tmp=${tmp/Avr/Apr} tmp=${tmp/Mai/May}
tmp=${tmp/Jui/Jul} tmp=${tmp/Aou/Aug}
sql_date=$(date +%Y%m%d -d "$tmp")
With sed:
tmp=$(sed 's/Fev/Feb;s/Avr/Apr;s/Mai/May;s/Jui/Jul;s/Aou/Aug' <<<"$fr_date")
sql_date=$(date +%Y%m%d -d "$tmp")
Solution 2: Assign to each month its corresponding number:
#!/bin/bash
# Requires bash 4 for associative arrays
declare -A month_map=(
[Jan]=01 [Fev]=02 [Mar]=03 [Avr]=04 [Mai]=05 [Jun]=06
[Jui]=07 [Aou]=08 [Sep]=09 [Oct]=10 [Nov]=11[Dec]=12
)
IFS=- read -r day month year <<<"$fr_date"
sql_date=$year${month_map[$month]}$day

Convert date String to number on Solaris shell script gives No such file or directory

I have a date in the format "Thu Sep 22 3:50 2016", and I want to convert it to format: "2016-09-22"
I tried the following shell script, which works fine for 'date', but gives error for user specified string: (I am working on Solaris platform). Any inputs will be helpful.
Input:
#!/usr/bin/sh
mydate="Thu Sep 22 3:50 2016"
echo `date +"%Y-%m-%d"`
echo `$mydate +"%Y-%m-%d"`
Output
./testShell.sh
**2016-09-22**
./testShell.sh[6]: Thu: not found **[No such file or directory]**
Any pointers please?
Under Solaris 11, many GNU utilities are available under the /usr/gnu/bin directory so you just need to slightly modify your script to either use the full path the the GNU variant :
#!/bin/sh
mydate="Thu Sep 22 3:50 2016"
date +"%Y-%m-%d"
/usr/gnu/bin/date -d "$mydate" +"%Y-%m-%d"
or use the already existing symlink prefixed by g (for GNU):
gdate -d "$mydate" +"%Y-%m-%d"
or set your PATH to look at /usr/gnu/bin first and keep your script unchanged.
PATH=/usr/gnu/bin:$PATH
You can try something like this;
#!/bin/bash
mydate="Thu Sep 22 3:50 2016"
date +"%Y-%m-%d"
date -d "$mydate" "+%Y-%m-%d"

sed: mass converting epochs amongst random other text

Centos / Linux
Bash
I have a log file, which has lots of text in and epoch numbers all over the place. I want to replace all epochs whereever they are into readable date/time.
I've been wanting to this via sed, as that seems the tool for the job. I can't seem to get the replacement part of sed to actually parse the variable(epoch) to it for conversion.
Sample of what I'm working with...
echo "Some stuff 1346474454 And not working" \
| sed 's/1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/'"`bpdbm -ctime \&`"'/g'
Some stuff 0 = Thu Jan 1 01:00:00 1970 And not working
The bpdbm part will convert a supplied epoch variable into useful date. Like this..
bpdbm -ctime 1346474454
1346474454 = Sat Sep 1 05:40:54 2012
So how do i get the "found" item to be parsed into a command. As i don't seem to be able to get it to work.
Any help would be lovely. If there is another way, that would be cool...but i suspect sed will be quickest.
Thanks for your time!
that seems the tool for the job
No, it is not. sed can use & only itself, there is no way how to make it an argument to a command. You need something more powerful, e.g. Perl:
perl -pe 'if ( ($t) = /(1[0-9]+)/ ) { s/$t/localtime($t)/e }'
You can do it with GNU sed, the input:
infile
Some stuff 1346474454 And not working
GNU sed supports /e parameter which allows for piping command output into pattern space, one way to take advantage of this with bpdbm:
sed 's/(.*)(1[0-9]{9})(.*)/echo \1 $(bpdbm -ctime \2) \3/e' infile
Or with coreutils date:
sed 's/(.*)(1[0-9]{9})(.*)/echo \1 $(date -d #\2) \3/e' infile
output with date
Some stuff Sat Sep 1 06:40:54 CEST 2012 And not working
To get the same output as with bpdbm:
sed 's/(.*)(1[0-9]{9})(.*)/echo "\1$(date -d #\2 +\"%a %b %_d %T %Y\")\3"/e' infile
output
Some stuff Sat Sep 1 06:40:54 2012 And not working
Note, this only replaces the last epoch found on a line. Re-run if there are more.

`date` command on OS X doesn't have ISO 8601 `-I` option?

In a Bash script, I want to print the current datetime in ISO 8601 format (preferably UTC), and it seems that this should be as simple as date -I:
http://ss64.com/bash/date.html
But this doesn't seem to work on my Mac:
$ date -I
date: illegal option -- I
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
And indeed, man date doesn't list this option.
Anyone know why this is, or any other (easy) way for me to print the date in ISO 8601 format? Thanks!
You could use
date "+%Y-%m-%d"
Or for a fully ISO-8601 compliant date, use one of the following formats:
date -u +"%Y-%m-%dT%H:%M:%SZ"
Output:
2011-08-27T23:22:37Z
or
date +%Y-%m-%dT%H:%M:%S%z
Output:
2011-08-27T15:22:37-0800
In GNU date date -I is the same as date +%F, and -Iseconds and -Iminutes also include time with UTC offset.
$ date +%F # -I or +%Y-%m-%d
2013-05-03
$ date +%FT%T%z # -Iseconds or +%Y-%m-%dT%H:%M:%S%z
2013-05-03T15:59:24+0300
$ date +%FT%H:%M # -Iminutes or +%Y-%m-%dT%H:%M%z
2013-05-03T15:59+0300
-u is like TZ=UTC. +00:00 can be replaced with Z.
$ date -u +%FT%TZ
2013-05-03T12:59:24Z
These are also valid ISO 8601 date or time formats:
20130503T15 (%Y%m%dT%M)
2013-05 (%Y%m)
2013-W18 (%Y-W%V)
2013-W18-5 (%Y-W%V-%u)
2013W185 (%YW%V%u)
2013-123 (%Y-%j, ordinal date)
2013 (%Y)
1559 (%H%M)
15 (%H)
15:59:24+03 (UTC offset doesn't have to include minutes)
These are not:
2013-05-03 15:59 (T is required in the extended format)
201305 (it could be confused with the YYMMDD format)
20130503T15:59 (basic and exteded formats can't be mixed)
A short alternative that works on both GNU and BSD date is:
date -u +%FT%T%z
The coreutils package provides GNU versions of tools. To install:
$ brew install coreutils
You can see what's provided:
$ brew list coreutils
Notice it comes with date:
$ brew list coreutils | grep date
This is the standard GNU date command so it'll take the -I switch:
$ gdate -I
2016-08-09
Just use normal date formatting options:
date '+%Y-%m-%d'
Edit: to include time and UTC, these are equivalent:
date -u -Iseconds
date -u '+%Y-%m-%dT%k:%M:%S%z'
Taking the other answers one step further, you could add a function to your ~/.bashrc or ~/.zshrc to add the date -I flag:
date() {
if [ "$1" = "-I" ]; then
command date "+%Y-%m-%dT%H:%M:%S%z"
else
command date "$#"
fi
}
It's not a feature of Bash, it's a feature of the date binary. On Linux you would typically have the GNU coreutils version of date, whereas on OSX you would have the BSD legacy utilities. The GNU version can certainly be installed as an optional package, or you can roll your own replacement - I believe it should be a simple one-liner e.g. in Perl.
There's a precompiled coreutils package for Mac OS X available at:
http://rudix.org/packages-abc.html#coreutils.
I regularly use 'date -I' in Linux when saving files. ex: touch x.date -I. While the equivalent in MacOS is 'date +%F', it is a bit awkward to type every time I save a file. So, I set an alias "alias dt='date +%F'" then touch x.dt gives me the date.

Get date of some UNIX time

How can I convert UNIX time to date format?
Smth like
$> date ???? 1300000000
Mar 13 2011 07:06:40 GMT
Your date command might understand the # prefix. Try:
$ date -d #1300000000
Sun Mar 13 08:06:40 CET 2011
If -d doesn't work for you, thats probably because it only works like that for GNU date.
For BSD, OSX, etc. one would ordinarily use:
date -r 1300000000

Resources