Convert Date Format

Hello,
I want to change the format of date value in variable.

e.g. cur_date = '2013/03/13 14:24:50' (yyyy/mm/dd hh24:mi:ss)

I want to change this to '13-MAR-2013 14:24:50

Following code coverts the current date to format I am looking for. But I do not know how this can be done for a date in different format that is stored in a variable.

date +'%d-%b-%Y %H:%M:%S' -d "$year$month$day $hour:$min:$sec"

Try:

date +'%d-%b-%Y %H:%M:%S' -d "$curdate"
$ cur_date='2013/03/13 14:24:50'
$ date -d "$cur_date" +'%d-%b-%Y %T'
13-Mar-2013 14:24:50

I am not getting the expected output of 13-MAR-2013 14:24:50

elise->DEV> echo $curr_date
2013/03/13 14:24:50
elise->DEV> date +'%d-%b-%Y %H:%M:%S' -d "$curr_date"
27-Nov-2013 16:17:27
elise->DEV> date -d "$curr_date" +'%d-%b-%Y %T'clear
date: illegal option -- d
usage:  date [-u] mmddHHMM[[cc]yy][.SS]
        date [-u] [+format]
        date -a [-]sss[.fff]
elise->DEV> 

You need GNU date to use the -d option of date.

If you system doesn't have that available you may need to use a perl program like this:

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

my ($yyyy, $mm, $dd, $hh, $min, $ss) = split(/[:\/ ]/, $ARGV[0]);
print strftime("%d-%b-%Y %T\n", localtime(timelocal($ss,$min,$hh,$dd,$mm-1,$yyyy)));

Save as format_date.pl and run it like this:

$ cur_date='2013/03/13 14:24:50'
$ ./format_date.pl "$cur_date"
13-Mar-2013 14:24:50

With a recent (1993 or later) Korn shell or bash, you could also use:

#!/bin/ksh
cur_date="${1:-2013/03/13 13:24:50}"
printf "Processing date: %s\n" "$cur_date"
amn="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
y=${cur_date%%/*}
m=${cur_date:5:2}
dm=${m#0}
d=${cur_date:8:2}
t=${cur_date#* }
printf "%s-%s-%s %s\n" "$d" "${amn:$(((dm-1)*3)):3}" "$y" "$t"

If you name this script tester and invoke it without arguments, you'll get:

Processing date: 2013/03/13 13:24:50
13-MAR-2013 13:24:50

If you invoke it with an operand, for example:

tester "2013/09/22 12:34:56"

you'll get:

Processing date: 2013/09/22 12:34:56
22-SEP-2013 12:34:56

You could also use an array for the months but initialiser code is different for ksh and bash, which should work on older versions that don't support the substring expansion stuff.

I still like the perl solution as it gives you flexibility to user other date % formatters.

#!/bin/ksh
cur_date="${1:-2013/03/13 13:24:50}"
printf "Processing date: %s\n" "$cur_date"
set -A amn JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
IFS='/ '
set -- $cur_date
printf "%s-%s-%s %s\n" "$3" "${amn[10#$2-1]}" "$1" "$4"

Get the following error for the script provided

DEV> vi dateformat.sh
#!/bin/ksh
cur_date="${1:-2013/03/13 13:24:50}"
printf "Processing date: %s\n" "$cur_date"
amn="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
y=${cur_date%%/*}
m=${cur_date:5:2}
dm=${m#0}
d=${cur_date:8:2}
t=${cur_date#* }
printf "%s-%s-%s %s\n" "$d" "${amn:$(((dm-1)*3)):3}" "$y" "$t"

"dateformat.sh" 10 lines, 278 characters

DEV> dateformat.sh 
Processing date: 2013/03/13 13:24:50
./dateformat.sh[6]: m=${cur_date:5:2}: bad substitution

DEV> dateformat.sh 2013/12/11 14:20:25
Processing date: 2013/12/11
./dateformat.sh[6]: m=${cur_date:5:2}: bad substitution

DEV>

---------- Post updated at 10:54 AM ---------- Previous update was at 10:29 AM ----------

works great. Thank you very much. I wish it worked for bash as I am trying to do this in a script that is coded for bash already for oracle ebs and it not always easy to use ksh for oracle ebs unix scripts.

DEV> vi dateformat1.sh
#!/bin/ksh
cur_date="${1:-2013/03/13 13:24:50}"
printf "Processing date: %s\n" "$cur_date"
set -A amn JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
IFS='/ '
set -- $cur_date
printf "%s-%s-%s %s\n" "$3" "${amn[10#$2-1]}" "$1" "$4"
DEV> dateformat1.sh 
Processing date: 2013/03/13 13:24:50
13-MAR-2013 13:24:50
DEV> dateformat1.sh '2013/12/11 14:20:25'
Processing date: 2013/12/11 14:20:25
11-DEC-2013 14:20:25

DEV> 

This is the bash version of that code:

#!/bin/bash
cur_date="${1:-2013/03/13 13:24:50}"
printf "Processing date: %s\n" "$cur_date"
amn=(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC)
IFS='/ '
set -- $cur_date
printf "%s-%s-%s %s\n" "$3" "${amn[10#$2-1]}" "$1" "$4"

If you're using this method it in another script try defining it as a function, this then keeps any shell positional parameters intact. I also saved and restored IFS as later parts of your script will most likely depend on it.

#!/bin/bash
function dateformat1()
{
  amn=(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC)
  OIFS=$IFS
  IFS='/ '
  set -- $1
  IFS=$OIFS
  printf "%s-%s-%s %s\n" "$3" "${amn[10#$2-1]}" "$1" "$4"
}

dateformat1 "${1:-2013/03/13 13:24:50}"