How to convert time output from SQL*Plus TIMING to a Linux TIMESTAMP? [duplicate] - bash

Looking for a bash line to take a RSS date format such as "Fri, 13 Sep 2013 17:16:45 GMT" and convert it into milliseconds?
I've tried things as below they they do not produce in milliseconds. I'm running Mac OS X Snow Leopard 10.6.8.
524 date +%s -d "Fri, 13 Sep 2013 17:16:45 GMT"
525 date +%s -d "Fri 13 Sep 2013 17:16:45 GMT"
526 date +%s -d "Fri 13 Sep 2013 17:16:45"
527 date +%s -f "Fri, 13 Sep 2013 17:16:45 GMT"
528 date +%s -f "Fri, 13 Sep 2013 17:16:45 GMT"
514 date +%s -d "Fri, 13 Sep 2013 17:16:45 GMT"
515 date +%s -d "Fri, 13 Sep 2013 17:16:45"
516 date +%s -ud "Fri, 13 Sep 2013 17:16:45 GMT"
517 date +%s -ud "Fri, 13 Sep 2013 17:16:45"
512 date -d "Fri, 13 Sep 2013 17:16:45 GMT" "+%s"

Does the RSS date have fractional seconds?
If not, using BSD date (i.e. Mac OS X):
echo $(date -j -f "%a, %d %b %Y %H:%M:%S" "Fri, 13 Sep 2013 17:16:45" +%s)000
or, according to the Mac OS X manpage:
echo $(date -j -f "%a, %d %b %Y %H:%M:%S %Z" "Fri, 13 Sep 2013 17:16:45 GMT" +%s)000
If you have GNU date, the following rather simpler expression will work:
echo $(date +%s -d "Fri, 13 Sep 2013 17:16:45 GMT")000
Or you could use this, which will work with fractional seconds in the original time string:
echo $(($(date +%s%N -d "Fri, 13 Sep 2013 17:16:45.126 GMT")/1000000))

The date command gives you time in [s] resolution. Just append 3 zeroes, if that resolution is OK for you.
date +%s -d "Fri, 13 Sep 2013 17:16:45 GMT" | sed 's/..*/&000/'
If it's not, I'm afraid you'll have to write a C program, using the system call gettimeofday(). Let's call it gettimeofday.c:
#include <sys/time.h>
#include <stdio.h>
int main(void)
{
struct timeval t;
gettimeofday(&t, NULL);
printf("%d%d\n", t.tv_sec, t.tv_usec / 1000);
return 0;
}
To compile it you need gcc and make:
make gettimeofday
And then:
./gettimeofday
On second thoughts, my little program is totally useless, since you want to convert a given date to Unix time. But I'll leave it here, because it's so nice. :-)

You can use awk to add three zeros at the end of the output to make it in ms.
date +%s -d "Fri, 13 Sep 2013 17:16:45 GMT" | awk '{print $0"000"}'
or use sed to do the same :
date +%s -d "Fri, 13 Sep 2013 17:16:45 GMT" | sed -e "s|.*|&000|g"
The above don't work in Mac OS X Lion. You have to install GNU date which is in the coreutil package in MacPorts. You will then get gdate.
Instead you can use python to do this :
python -c'import time; print "%f" % (time.mktime(time.gmtime())*1000.)'

If you get an date: illegal time format error message on Mac OS X try using LANG=C date:
- echo $(date -j -f "%a, %d %b %Y %H:%M:%S %Z" "Fri, 13 Sep 2013 17:16:45 GMT" +%s)000 # date: illegal time format
+ echo $(LANG=C date -j -f "%a, %d %b %Y %H:%M:%S %Z" "Fri, 13 Sep 2013 17:16:45 GMT" +%s)000

Related

How to convert a timestamp to a different timezone in bash?

I have a time in GMT, that looks like this:
Wed Feb 13 04:46:54 +0000 2019
In a bash script on MacOS 10.14.3, I want to convert it to the user's local timezone. i.e., this one is 04, so changing it to my timezone would be -6, so it would end up something like this:
Tue Feb 12 22:46:54 CST 2019
Thanks in advance.
Is this what you are looking for ?
date -d "Wed Feb 13 04:46:54 +0000 2019 - 6 hour"
dt= "Wed Feb 13 04:46:54 +0000 2019"
tz="-6"
date -d "$dt $tz hour"
I ended up using something like this:
postYear=`TZ="${timeZone}" date -jf "%Y-%m-%d %H:%M:%S %z" "${postYear}-${postMonth}-${postDay} ${postHourGmt}:${postMinute}:${postSecond} +0000" +%Y`
...where the variables were giving input into the date that I wanted to pull something out of...
...and the year (%Y) was what I was pulling out.

Bash script to iterate through a specific time range, one second at a time

I am trying to create some sort of loop in bash that will iterate through a specific time range, one second at a time.
At each interval, it will perform a duty with that timestamp I.e. "Wed Mar 2 12:00:03 CDT 2018"
I am having a hard time wrapping my head around how to make a loop that will iterate every second of time, and when it hits 60 seconds, update the minute, etc.
Thoughts? This seems obvious but the right syntax escapes me.
this is one way of doing it, delegate time computations to date
$ for i in {1..10}; do date -d "+$i seconds"; done
Sun Mar 11 20:40:57 UTC 2018
Sun Mar 11 20:40:58 UTC 2018
Sun Mar 11 20:40:59 UTC 2018
Sun Mar 11 20:41:00 UTC 2018
Sun Mar 11 20:41:01 UTC 2018
Sun Mar 11 20:41:02 UTC 2018
Sun Mar 11 20:41:03 UTC 2018
Sun Mar 11 20:41:04 UTC 2018
Sun Mar 11 20:41:05 UTC 2018
Sun Mar 11 20:41:06 UTC 2018
Sun Mar 11 20:41:07 UTC 2018
if you want to iterate up to a certain time, change the for loop to a while loop and a counter.
To make a loop with time you need to format date/time in such a way that can be comparable. The most easy trick is to transform date to something that will look like an integer and you then use lt,le,eq,gt,ge operators of bash.
Consider this :
$ date
Mon Mar 12 00:16:29 EET 2018 #this format/data type is not comparable by bash
$ date +%Y%m%d%H%M%S
20180312001629 #this is an integer representing the current time
This is a sample loop from now up to a specific time point:
stop=$(date +%Y%m%d%H%M%S --date "2018-03-12 00:20:55")
while [[ $(date +%Y%m%d%H%M%S) -le $stop ]];do #comparing current date & time with stop date & time
echo "date now is $(date)";
sleep 1; #sleep 1 second
done
date now is Mon Mar 12 00:20:51 EET 2018
date now is Mon Mar 12 00:20:52 EET 2018
date now is Mon Mar 12 00:20:53 EET 2018
date now is Mon Mar 12 00:20:54 EET 2018
date now is Mon Mar 12 00:20:55 EET 2018
The trick here is that the command
stop=$(date +%Y%m%d%H%M%S --date "2018-03-12 00:20:55")
converts given date (using the --date flag) to a kind of integer format.
Then the while loop keeps comparing current date in the same integer format with the stop date.
This is a similar script to start/stop at a specific time, but it is a bit "resources hungry" since it keeps comparing current time to start time:
date; #just print the current date & time
compl=false;
start=$(date +%Y%m%d%H%M%S --date "2018-03-12 01:45:50");
stop=$(date +%Y%m%d%H%M%S --date "2018-03-12 01:45:55");
while true;do
while [[ $(date +%Y%m%d%H%M%S) -ge $start ]] && [[ $(date +%Y%m%d%H%M%S) -le $stop ]];do
echo "date now is $(date)";
sleep 1;
compl=true;
done;
($compl) && break;
done
Mon Mar 12 01:45:37 EET 2018
date now is Mon Mar 12 01:45:50 EET 2018
date now is Mon Mar 12 01:45:51 EET 2018
date now is Mon Mar 12 01:45:52 EET 2018
date now is Mon Mar 12 01:45:53 EET 2018
date now is Mon Mar 12 01:45:54 EET 2018
date now is Mon Mar 12 01:45:55 EET 2018
An alternative to start/stop a script at specific time would be to use epoch date / epoch seconds.
Epoch date is measured in seconds since the epoch (1970-01-01 UTC).
Every date can be expressed as epoch seconds, using the format date +%s.
date #just print the current date & time
start="2018-03-12 02:17:52"
stop="2018-03-12 02:17:57"
timerequired=$(( $(date +%s --date "$start") - $(date +%s) ))
sleep $(($timerequired)) #sleep till the starting time
while [[ $(date +%s) -le $(date +%s --date "$stop") ]];do
echo "date now is $(date)";
sleep 1;
done
Mon Mar 12 02:17:39 EET 2018
date now is Mon Mar 12 02:17:52 EET 2018
date now is Mon Mar 12 02:17:53 EET 2018
date now is Mon Mar 12 02:17:54 EET 2018
date now is Mon Mar 12 02:17:55 EET 2018
date now is Mon Mar 12 02:17:56 EET 2018
date now is Mon Mar 12 02:17:57 EET 2018
Finally, you can use external tools to automate things based on date & time like cron, anacron , at, etc
Echo a date for every second in a range:
from=$(date -d "Wed Mar 2 12:59:58 CDT 2018" +%s)
to=$(date -d "Wed Mar 2 13:00:04 CDT 2018" +%s)
for s in $(seq $from $to); do echo $(date -d #$s); done
The date -d takes a well formed date as input. +%s formats it into seconds since epoch. So you get two big values like from=1520013598, to=...3604. The date -d #1520013598 transforms the timestamp back to a human readable date.
Your range might be in a variable like start and stop, and you might like to foobar ($time) instead of echoing it:
start="Wed Mar 2 12:59:58 CDT 2018"
stop="Wed Mar 2 13:00:04 CDT 2018"
from=$(date -d "$start" +%s)
to=$(date -d "$stop" +%s)
for s in $(seq $from $to)
do
timestamp=$(date -d #$s)
foobar $timestamp
done

string "Fri Dec 16 16:12:24 CST 2016" to timestamp by shell

I have some string (read from a file) ,such as "Fri Dec 16 16:12:24 CST 2016", and How to convert this string to timestamp, by shell?
I need timestamp,such as Fri Dec 16 16:27:28 CST 2016 -> 1481876854
shell cmd date print Fri Dec 16 16:12:24 CST 2016,so I think date have some method to do it.
but I can't find a solution,Can someone help me?
macos 10.12.2
For the FreeBSD date, you can use the -j flag with format as -f "%a %b %d %T %Z %Y"
date -j -f "%a %b %d %T %Z %Y" "Fri Dec 16 16:27:28 CST 2016" +"%s"
1481876854
If you are using GNU based date command, you can convert to EPOCH timestamp using the -d flag, i.e.
date -d"Fri Dec 16 16:27:28 CST 2016" +%s
1481876854
Based on your spec (time format) and if date doesn't work or is not available, the heavy tool
echo "Fri Dec 16 16:27:28 CST 2016" \
| gawk -F '[[:blank:]:]' 'BEGIN{
split( "Jan Feb Mar Apr May Jun Jul Agu Sep Oct Nov Dec", Temp, " ")
for (t in Temp) Month[ Temp[t]] = t < 10 ? "0" t : t
}
{
# mktime assume ISO C time format: "YYYY MM DD HH MM SS [DST]"
ISOTime = sprintf( "%d %s %s %s %s %s\n", $8, Month[ $2], $3 < 10 ? "0" $3 : $3, $4, $5, $6)
print mktime( ISOTime)
}
'

Loop minutes and echo with bash

I want to iterate all the minutes in a month (the purpose will be to generate a CSV file).
But when I try this:
d="2016-09-01 00:00:00"
while [ "$d" != "2016-09-30 00:00:00" ]; do
echo $d
d=$(date --utc "+%Y-%m-%d %H:%M:00" -d "$d + 1 minute" )
done
Both the hour and minute are being incremented:
2016-09-01 00:00:00
2016-09-01 01:01:00
2016-09-01 02:02:00
2016-09-01 03:03:00
2016-09-01 04:04:00
2016-09-01 05:05:00
2016-09-01 06:06:00
2016-09-01 07:07:00
2016-09-01 08:08:00
What am I doing wrong and how to correctly loop minutes?
I would work with Unix timestamps instead.
d=$(date --utc +%s -d "2016-09-01 00:00:00")
end=$(date --utc +%s -d "2016-09-30 00:00:00")
while [ "$d" != "$end" ]; do
date --utc "+%Y-%m-%d %H:%M:00" -d "#$d"
d=$(( d + 60 ))
done
You can add timezone UTC after your date string variable $d to get the right output:
d="2016-09-01 00:00:00"
for ((i=0; i<=60; i++)); do
date --utc -d "$d UTC + $i minute"
done
Thu Sep 1 00:00:00 UTC 2016
Thu Sep 1 00:01:00 UTC 2016
Thu Sep 1 00:02:00 UTC 2016
Thu Sep 1 00:03:00 UTC 2016
Thu Sep 1 00:04:00 UTC 2016
Thu Sep 1 00:05:00 UTC 2016
...
...
Thu Sep 1 00:55:00 UTC 2016
Thu Sep 1 00:56:00 UTC 2016
Thu Sep 1 00:57:00 UTC 2016
Thu Sep 1 00:58:00 UTC 2016
Thu Sep 1 00:59:00 UTC 2016
Thu Sep 1 01:00:00 UTC 2016
Note use of UTC after $d.
Using + after a time component in the date string is used for ' time zone correction' not for doing what you want to do. Interestingly, inverting date and time works:
$ date "+%Y-%m-%d %H:%M:00" -d "21:31:00 2016-09-03 + 1 minute "
2016-09-03 21:32:00
while the other way around messes with timezones and offsets so the result might depend on your local configuration:
$ TZ=Europe/London date "+%Y-%m-%d %H:%M:00" -d "2016-09-03 21:32:00 + 1 minute "
2016-09-03 21:33:00
$ TZ=Europe/Brussels date "+%Y-%m-%d %H:%M:00" -d "2016-09-03 21:32:00 + 1 minute "
2016-09-03 22:33:00
$ TZ=Asia/Singapore date "+%Y-%m-%d %H:%M:00" -d "2016-09-03 21:32:00 + 1 minute "
2016-09-04 04:33:00

How to get epoch time in shell script (for ksh)?

How to get epoch time in shell script (for ksh)?
I am interested in getting epoch time for the start of day (so e.g. now is July 28th, 2011 ~ 14:25:00 EST, I need time at midnight).
If you have GNU date,
epoch=$( date -d 00:00 +%s )
Otherwise, if you have tclsh,
epoch=$( echo 'puts [clock scan 00:00]' | tclsh )
Otherwise,
epoch=$( perl -MTime::Local -le 'print timelocal(0,0,0,(localtime)[3..8])' )
ksh's printf '%(fmt)T' supports time calculating. For example:
$ printf '%T\n' now
Mon Mar 18 15:11:46 CST 2013
$ printf '%T\n' '2 days ago'
Sat Mar 16 15:11:55 CST 2013
$ printf '%T\n' 'midnight today'
Mon Mar 18 00:00:00 CST 2013
$

Resources