Convert Current Date to Unix timestamp but using Days - shell

In Solaris, I am trying to write a shell script that converts current date to the number of days after 1/1/1970 for Unix. This is because etc/shadow isn't using Epoch time but instead a 'days format'
i.e "root:G9yPfhFAqvlsI:15841::::::" where the 15841 is a date.
So in essence what command do I use to find out the epoch time for now and then convert that to days.

You probably don't have GNU tools, which might make things easier. This is simple enough though:
perl -le 'print int(time/86400)'

I found some pseudo code to calculate it from the basics:
if month > 2 then
month=month+1
else
month=month+13
year=year-1
fi
day=(year*365)+(year/4)-(year/100)+(year/400)+(month*306001/10000)+day
days_since_epoch=day-719591
Credit: http://www.unix.com/shell-programming-and-scripting/115449-how-convert-date-time-epoch-time-solaris.html). On the same forum thread, another poster said this would work in Solaris:
truss /usr/bin/date 2>&1 | grep ^time | awk -F"= " '{print $2}'

Solaris date utility doesn't support %s format. However, nawk utility has srand() function that returns date in seconds when there's no parameter passed to it.
nawk 'BEGIN {print srand()}'
Results in
1405529923
To get the days instead of seconds, you can divide the result by 86400.
nawk 'BEGIN {printf("%d", srand() / 86400)}'

Related

Adding months using shell script

Currently I have a below record in a file.
ABC,XYZ,123,Sep-2018
Looking for a command in linux which will add months and give the output. For example If I want to add 3 months. Expected output is:
ABC,XYZ,123,Dec-2018
Well,
date -d "1-$(echo "ABC,XYZ,123,Sep-2018" | awk -F "," '{ print $4 }')+3 months" "+%b-%Y"
(Careful, that code continues past the edge of the box.)
Shows you how to get it working. Just replace the echo with a shell variable as you loop through the dates.
Basically, you use awk to grab just the date portion, add a 1- to the front to turn it into a real date then use the date command to do the math and then tell it to give you just the month abbreviation and year.
The line above gives just the date portion. The first part can be found using:
stub=`echo "ABC,XYZ,123,Dec-2018" | awk -F "," '{ printf("%s,%s,%s,",$1,$2,$3) }'`
You can use external date or (g)awk's datetime related function to do it. However you have to prepare the string to parse. Here is another way to do the job:
First prepare an index file, we name it month.txt:
Jan
Feb
......
...
Nov
Dec
Then run this:
awk -F'-|,' -v OFS="," 'NR==FNR{m[NR]=$1;a[$1]=NR;next}
{i=a[$4]; if(i==12){i=1;++$5}else i++
$4=m[i]"-"$5;NF--}7' month.txt file
With this example file:
ABC,XYZ,123,Jan-2018
ABC,XYZ,123,Nov-2018
ABC,XYZ,123,Dec-2018
You will get:
ABC,XYZ,123,Feb-2018
ABC,XYZ,123,Dec-2018
ABC,XYZ,123,Jan-2019
update
Oh, I didn't notice that you want to add 3 months. Here is the updated codes for it:
awk -F'-|,' -v OFS="," 'NR==FNR{m[NR]=$1;a[$1]=NR;next}
{i=a[$4]+3; if(i>12){i=i-12;++$5}
$4=m[i]"-"$5;NF--}7' month.txt file
Now with the same input, you get:
ABC,XYZ,123,Apr-2018
ABC,XYZ,123,Feb-2019
ABC,XYZ,123,Mar-2019

awk text replacement script

I'm trying to write a script that takes today's date and replaces it with tomorrow's date. My problem relies on the awk command. Here's what I've done so far:
date_today=`date`
day_today=`echo $date_today | awk '{print $3}'`
day_tomorrow=$(( ++day_today ))
date_tomorrow=`echo $date_today | awk '{print $3=$day_tomorrow}'`
But it doesn't print the expected date. I'm just trying to replace today's date number by tomorrow's date number.
Since you haven't shown in which format you need to the complete date so I am assuming it could be year-month-date format.
Solution 1st: With GNU date in case you have GNU date in your system then following may help you on same.
date --date="+1 day" +"%Y-%m-%d"
Solution 2nd: With a non-GNU date following may help you in same.(Since I have GNU date in my system so I couldn't test it)
date -d #$(( $(date +"%s") + 86400)) +"%Y-%m-%d"
Also in case you don't need it in above format you could change it by changing %Y-%m-%d in above codes.

How to find out uptime in minutes?

How to find out and save to file uptime on Solaris in minutes without cutting and converting it ? Is there any elegant way of doing it? Thanks for answers
Here is a reliable and accurate way to get the number of minutes since last boot on Solaris:
kstat -n system_misc |
nawk '/boot_time/ {printf("%d minutes\n",(srand()-$2)/60)}'
Under nawk, the srand() function returns the number of seconds since the epoch while the boot_time kstat statistic returns the number of seconds since the epoch at boot time. Subtracting the former from the latter gives the number of seconds, and dividing it further by 60 gives the number of minutes since last boot.
On Solaris, the uptime(1) command is just a link to w(1). You can find its source code at https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/w/w.c.
There, you will find that uptime(1) gets the boot time as recorded in /var/run/utmpx. Just as they do, you can read the data from this file using the getutxent(3) family of functions, and look for a record with ut_type == BOOT_TIME. In this record, look at the ut_tv field, which is a struct timeval and contains the seconds and microseconds of the boot time. From this you can calculate how long the system has been up.
(Edit: I just noticed the shell tag. This solution would be more suitable for calling from a C program. Oh well, maybe it will be useful to someone.)
Not completely sure that this will work on Solaris but...
uptime | awk -F ',' ' {print $1} ' | awk ' {print $3} ' | awk -F ':' ' {hrs=$1; min=$2; print hrs*60 + min} '
A small improvement on #jilliagre's suggestion is to use kstat(1m) to extract more information for you before passing to nawk(1):
$ kstat -p -n system_misc -s boot_time| nawk '{printf("%d minutes\n",(srand()-$2)/60)}'
26085 minutes
-p means "parseable output", -s selects the specific stat underneath -n module name.

Comparing and transforming a date that is piped to (probably) awk?

I've got a reasonably complicated string of piped shell commands (let's assume it's bunch | of | commands), which together produces several rows of output, in this format:
some_path/some_file.csv 1439934121
...where 1439934121 is the file's last-modified timestamp.
What I need to do is see if it's a timestamp on the current day, i.e. on or after last midnight, and then include just the lines where that is true.
I assume this means that some string (e.g. the word true) should either replace or be appended to the timestamps of those lines for grep to distinguish them from ones where the timestamps are those of an earlier date.
To put it in shell command terms:
bunch | of | commands | ????
...should produce:
some_path/some_file.csv true or some_path/some_file.csv 1439934121 true
...for which I could easily grep (obviously assuming that last midnight <= 1439934121 <= current time).
What kind of ???? would do this? I'm almost certain that awk can do what I need it to, so I've looked at it and date, but I'm basically doing awk-by-google with no skills and getting nowhere.
Don't feel constrained by my tool assumptions; if you can achieve this with alternate means, given the output of bunch | of | commands but still using shell tools and piping, I'm all ears. I'd like to avoid temp files or Perl, if possible :-)
I'm using gawk + bash 4.3 on Ubuntu Linux, specifically, and have no portability concerns.
Since today 00:00:00 with the %s format returns the unix timestamp of that moment:
$ date -d'today 00:00:00'
Thu Sep 3 00:00:00 CEST 2015
$ date -d 'today 00:00:00' "+%s"
1441231200
You can probably pipe to an awk doing something like:
... | awk -v midnight="$(date -d 'today 00:00:00' '+%s')" '{$2= ($2>midnight) ? "true" : "false"}1'
That is, use the ternary operator to check the value of $2 and replace with either of the values true/false depending on the result:
awk -v midnight="$(date ...)" '{$2= ($2>midnight) ? "true" : "false"}1'
Test
$ cat a
hello 1441231201
bye 23
$ awk -v midnight="$(date -d 'today 00:00:00' '+%s')" '{$2= ($2>midnight) ? "true" : "false"}1' a
hello true
bye false

How to convert time format from "2010-10-08 00:00:01" to "1286467201" in awk

In awk, Is there a way to convert the time format from "2010-10-08 00:00:01" to 1286467201
as using the command "date"
$ date +%s -d '2010-10-08 00:00:01'
1286467201
GNU awk has a mktime function that can do the job. However, it's crucial to be aware of timezones. The string "2010-10-08 00:00:01" does not contain enough information to define a specific time. If you assume it is in UTC you can do:
$ echo 2010-10-08 00:00:01 | \
TZ=UTC gawk '{ tstr=$1" "$2; gsub(/[\-:]/, " ", tstr); print mktime(tstr); }'
1286496001
If you don't specify the TZ variable you end up with the server's time zone (which should be UTC anyway, but a lot of folks use local time on servers, so it's not a safe assumption).
You can get UTC output from your date command by altering it slightly:
$ date +%s -u -d '2010-10-08 00:00:01'

Resources