How can I change the format of a date from the command line? - command-line

What's the quickest way to convert a date in one format, say
2008-06-01
to a date in another format, say
Sun 1st June 2008
The important bit is actually the 'Sun' because depending on the dayname, I may need to fiddle other things around - in a non-deterministic fashion. I'm running GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0).
[Background: The reason that I want to do it from the command line, is that what I really want is to write it into a TextMate command... It's an annoying task I have to do all the time in textMate.]

$ date -d '2005-06-30' +'%a %F'
Thu 2005-06-30
See man date for other format options.
This option is available on Linux, but not on Darwin. In Darwin, you can use the following syntax instead:
date -j -f "%Y-%m-%d" 2006-06-30 +"%a %F"
The -f argument specifies the input format and the + argument specifies the output format.
As pointed out by another poster below, you would be wise to use %u (numeric day of week) rather than %a to avoid localization issues.

Reading the date(1) manpage would have revealed:
-j Do not try to set the date. This allows you to use the -f flag
in addition to the + option to convert one date format to another.

Thanks for that sgm. So just so I can come back to refer to it -
date -j -f "%Y-%m-%d" "2008-01-03" +"%a%e %b %Y"
^ ^ ^
parse using | output using
this format | this format
|
date expressed in
parsing format
Thu 3 Jan 2008
Thanks.

date -d yyyy-mm-dd
If you want more control over formatting, you can also add it like this:
date -d yyyy-mm-dd +%a
to just get the Sun part that you say you want.

date -d ...
doesn't seem to cut it, as I get a usage error:
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
I'm running GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0), and as far as the man goes, date -d is just for
-d dst Set the kernel's value for daylight saving time. If dst is non-
zero, future calls to gettimeofday(2) will return a non-zero for
tz_dsttime.

If you're just looking to get the day of the week, don't try to match strings. That breaks when the locale changes. The %u format give you the day number:
$ date -j -f "%Y-%m-%d" "2008-01-03" +"%u"
4
And indeed, that was a Thursday. You might use that number to index into an array you have in your program, or just use the number itself.
See the date and strftime man pages for more details. The date manpage on OS X is the wrong one, though, since it doesn't list these options that work.

Related

Unix string to date conversion, what is wrong

I know the topic has already emerged and some of the posts give a good summary like the one here: Convert string to date in bash . Nevertheless, I encounter a problem presented below with an example I should solve:
date +'%d.%m.%y' works as desired and returns 05.12.20 but the inverse operation I should use to convert strings to date fails:
date -d "05.12.20" +'%d.%m.%y'
date: invalid date ‘05.12.20’
and this is exactly what I need. The Unix date formatting I have also checked on https://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/ but it seems to be in line with that. What is the problem? I also tried to supply time zone indicators like CEST but they did not solve the problem.
Try
date -d "05-12-20" +'%d.%m.%y'
UNIX date expects either - or / as a date separator.
However, if your input really must be in the format "05.12.20" (i.e. using .), then you can convert it to the format expected by UNIX date:
date -d `echo "05.12.20" | sed 's/\./-/g'` +'%d.%m.%y'

How to get ISO8601 seconds format from “date” in busybox?

[DISCLAIMER: This question is intended to be in question and answer format. The solution has already been determined and is provided with the question.]
Without adequate examples from the busybox help section, I was unable to determine the how to get date to print out the 'seconds' version of iso8601. The help does not provide examples to help understand the syntax required. Here are different ways that were tried to get the desired format without much luck. How does one get ISO8901 seconds format from the "date" in busybox?
Here is what was tried:
➤ date -I=seconds
➤ date -I SPEC='seconds'
➤ date -I seconds
➤ date -I='seconds'
➤ date -I 'seconds'
➤ date -I['seconds']
➤ date -I TIMESPEC='seconds'
➤ date -I TIMESPEC=seconds
Note I have tried to use the Ubuntu version of date and was able to figure out how to get the iso8601=seconds format of date, but not in busybox...
Here is what the help of date shows for Busybox 1.22.1:
BusyBox v1.22.1 (2014-09-26 07:33:17 CEST) multi-call binary.
Usage: date [OPTIONS] [+FMT] [TIME]
Display time (using +FMT), or set time
[-s,--set] TIME Set time to TIME
-u,--utc Work in UTC (don't convert to local time)
-R,--rfc-2822 Output RFC-2822 compliant date string
-I[SPEC] Output ISO-8601 compliant date string
SPEC='date' (default) for date only,
'hours', 'minutes', or 'seconds' for date and
time to the indicated precision
-r,--reference FILE Display last modification time of FILE
-d,--date TIME Display TIME, not 'now'
-D FMT Use FMT for -d TIME conversion
The documentation (i.e., date --help) is confusing. Example usages in the documentation can help reduce this confusion and at least help socialize the syntax.
The main difference from the above examples is a "space" that messes up the command. See below:
➤ date -I 'seconds'
date: invalid date 'seconds'
Was off by a hair. It needed a space removed:
➤ date -I'seconds'
2017-07-09T17:29:54-0400
Now busybox date is happy.

How to get ISO8601 seconds format from "date" in busybox?

Without adequate examples I keep going around in circles to get the 'seconds' version of iso8601 printed out by 'date'. Please look at the help that is provided with date with busybox 1.22.1. I can't seem to understand the syntax required. Examples speaks louder than words in my experience and I haven't found anything that could be useful online.
Here is what I tried:
➤ date -I=seconds
➤ date -I SPEC='seconds'
➤ date -I seconds
➤ date -I='seconds'
➤ date -I 'seconds'
➤ date -I['seconds']
➤ date -I TIMESPEC='seconds'
➤ date -I TIMESPEC=seconds
Note I have tried to use the Ubuntu version of date and was able to figure out how to get the iso8601=seconds format of date, but not in busybox...
Here is what the help of date shows for Busybox 1.22.1:
BusyBox v1.22.1 (2014-09-26 07:33:17 CEST) multi-call binary.
Usage: date [OPTIONS] [+FMT] [TIME]
Display time (using +FMT), or set time
[-s,--set] TIME Set time to TIME
-u,--utc Work in UTC (don't convert to local time)
-R,--rfc-2822 Output RFC-2822 compliant date string
-I[SPEC] Output ISO-8601 compliant date string
SPEC='date' (default) for date only,
'hours', 'minutes', or 'seconds' for date and
time to the indicated precision
-r,--reference FILE Display last modification time of FILE
-d,--date TIME Display TIME, not 'now'
-D FMT Use FMT for -d TIME conversion
The documentation (i.e., the help) is confusing and doesn't lead to a pleasant experience for a simple functionality. Instead the documentation needs to be re-written such that example command line inputs are also a part of help (at least to get the syntax down). In any case, I answered my own question.
The main and very subtle difference in one of my tries that I happened to miss:
➤ date -I 'seconds'
date: invalid date 'seconds'
Was off by a hair. It needed to remove the space:
➤ date -I'seconds'
2017-07-09T17:29:54-0400
Now busybox date is happy.

Extract day from non standard Unix date

I can see that UNIX easily handles a standard date format 'yyyy-mm-dd'. Date function can easily extract day form standard date format like this
date -d '2016-12-9 00:00:00' '+%d'
output: 09
But I can't figure out a way to get the same result using a non-standard date format. My date format is 'mm-dd-yyyy'.
GNU date which you are most likely using because of the -d switch, doesn't allow custom formatting of dates, unlike the FreeBSD version which supports with the -f input_fmt for converting custom date formats.
With GNU date and bit of manipulation with sed, you can achieve what you are trying to do.
Using sed converting your input date in mm-dd-yyyy to a format GNU date can understand.
customDate=$(echo "12-09-2016 00:00:00" | sed 's/\([0-9]\{2\}\)\-\([0-9]\{2\}\)\-\([0-9]\{4\}\) \(.*\)/\3-\1-\2 \4/')
Now customDate will have the date in the format 2016-12-09 00:00:00 format which you can pass to -d flag to get the required date. i.e.
date -d "$customDate" '+%d'
09
Or as a fancy "one-liner" they call it these days, without the use of the temporary variable.
date -d "$(echo "12-09-2016 00:00:00" | sed 's/\([0-9]\{2\}\)\-\([0-9]\{2\}\)\-\([0-9]\{4\}\) \(.*\)/\3-\1-\2 \4/')" '+%d'
09

BASH: How do you "split" the date command?

Cygwin user here (though if there's a suitable solution I will carry it over to K/Ubuntu, which I also use).
I have a Welcome message in my .bashrc that looks like the following:
SAD=(`date +%A-%B-%d-%Y`)
DUB=(`date -u +%k:%M`)
printf "Today's Date is: ${SAD}.\n"
printf "Dublin time is now ${DUB}. (24-Hour Clock)\n"
After numerous attempts to use whitespaces in the variable SAD above, I gave in and used hyphens. But I am, understandably, not satisfied with this band-aid solution. The problem, as I recall, was that every time I tried using quoted space, \s or some similar escape tag, along with the variables listed in the appropriate section of the GNU manpage for date, the variable for Year was either ignored or returned an error. What I do'nt want to have to do is resort to the full string as returned by date, but rather to keep the order in which I have things in the code above.
As I write this, it occurs to me that setting the IFS around this code for the Welcome message may work, provided I return it to defaults afterwards (the above appears at lines 13-17 of a 68-line .bashrc). However, I can't recall how to do that, nor am I sure that it would work.
Generally-speaking, .bashrc files are in valid BASH syntax, aren't they? Mine certainly resemble the scripts I've either written myself or tested from other sources. All I'm missing, I suppose, is the code for setting and unsetting the field separators around this message block.
No doubt anyone who comes up with a solution will be doing a favor not only to me, but to any other relative newbies on the Net taking their first (or thirteenth through seventeenth) steps in the world of shell scripting.
BZT
Putting
SAD=$(date "+%A %B %d %Y")
DUB=$(date -u +%k:%M)
echo "Today's Date is: ${SAD}."
echo "Dublin time is now ${DUB}. (24-Hour Clock)"
in my .bash_profile prints
Today's Date is: Thursday February 18 2010.
Dublin time is now 12:55. (24-Hour Clock)
I think that's what you want.
the problem is your array declaration.
SAD=(date +%A-%B-%d-%Y) just means you are putting the string "date" as element 0, and "+%A-%B-%d-%Y" as element 1. see for yourself
$ SAD=(date +%A-%B-%d-%Y) #<-- this is an array declaration
$ echo ${SAD[0]}
date
$ echo ${SAD[1]}
+%A-%B-%d-%Y
if you want the value of "date" command to be in a variable, use $(..), eg
$ SAD=$(date +%A-%B-%d-%Y)
$ echo ${SAD}
Thursday-February-18-2010
To get spaces, you need to quote the argument to date so that it's a single string. You're also erroneously declaring SAD and DUB as arrays, when what you really meant to do was evaluate them. Try this:
[/tmp]> $(date "+%A %B %d, %Y")
Thursday February 18, 2010
date +%A\ %B\ %d\ %Y
I found the combination that works:
SAD=$(date "+%A %B %d %Y")
echo $SAD
Thursday February 18 2010
Yet another instance when:
It pays to ask a question
It helps to know where to put your double quotes.
date obviously does not know from quoted space, but Bash does, so
it's a matter of "whispering in the right ear."
Thank you ghostdog74.
BZT