How do you get the last day of the last month in csh?
Here is the code so far. The cal command below almost works if you execute it from the (FreeBSD sh) command line, but I'm having trouble escaping it properly to run within a script. By almost work, I mean it returns 31, when the last day of February 2010 is 28.
#!/bin/csh
set lastdayoflastmonth=`cal `date '+%m'` `date '+%Y'` | grep . | fmt -1 | tail -1`
echo $lastdayoflastmonth
To be clear:
If today is March 26th 2010, it should return the number 28, which is the last day of the February 2010.
If today is July 1st 2010, it should return the number 30, which is the last day of June 2010.
Update: working answer received from Joshua Smith in comments below: date -v31d -v-1m '+%d' Thank you!
Just use the date command:
date -v31d +'%a'
will give you the date name of the last day of the current month
for next month:
date -v31d -v+1m +'%a'
If you want the previous month:
date -v31d -v-1m +'%a'
-- EDIT: commenter has question about GNU Date ---
If you are using gnu date (the above uses BSD date) you can use the -d flag. It's a little more complicated, though (gnu date doesn't do the same thing with month length fuzziness). to get the last day of the month for last month
for the current month:
date -d "$(date -d "next month" +%Y-%m-1) -1 day" +%a
and for next month
date -d "$(date -d "2 months" +%Y-%m-1) -1 day" +%a
for last month:
date -d "$(date +%Y-%m-1) -1 day" +%a
I think (if I recall correctly) that you have to double the backticks (``) when 'nesting' them.
Try (untested):
set lastdayoflastmonth=`cal ``date '+%m'`` ``date '+%Y'`` | grep . | fmt -1 | tail -1`
echo $lastdayoflastmonth
you can shorten your command to omit the grep/fmt. also, there is no need to cram them into one line.
set month=`date '+%m'`
set year=`date '+%Y'`
set lastdaymonth=`cal $month $year |tr -s " " "\n"|tail -1`
eg
$ tcsh
$ set month="02"
$ set year="2010"
$ set lastdaymonth=`cal $month $year |tr -s " " "\n"|tail -1`
$ echo $lastdaymonth
28
$ tcsh --version
tcsh 6.17.00 (Astron) 2009-07-10 (i386-intel-linux) options wide,nls,dl,al,kan,rh,color,filec
Related
I'm trying to figure out how to get the current hour rounded down to start of the hour and the next hour in bash?
For example, if I run my script:
./printHour.sh
and let's say the current time at execution is 13:04:12 - it would print
current hour is: 13:00:00
next hour is: 14:00:00
Progress so far: (but this gives 1hour ago so it does not work) - any ideas?
lastHour=$(date -d '1 hour ago' "+%H:%M:%S")
echo "current hour is: "$lastHour
You can use this utility function:
hrdt() { date -d "${1?} hour ago" '+%H:00:00'; }
Testing:
> hrdt
bash: 1: parameter not set
> hrdt 0
08:00:00
> hrdt 1
07:00:00
> hrdt 2
06:00:00
> hrdt 3
05:00:00
Could you please try following, written and tested as per shown samples, my date is GNU date version.
cat script.bash
#!/bin/bash
currentHour=$(date "+%H:00:00")
nextHour=$(date -d '+1 hour' "+%H:00:00")
echo "current hour is: $currentHour"
echo "next hour is: $nextHour"
When I run above script I get as follows:
current hour is: 06:00:00
next hour is: 07:00:00
Seems like you don't need anything special so this should do it:
date -d '1 hour ago' "+%H:00:00"
Why bother when you want exactly the hour where both %M and %S are expected to be zero?
You don't need date in this case; as seen below, built-in printf can generate formatted date-time strings too. Here -1 represents current time, and EPOCHSECONDS is a dynamic variable that expands to the number of seconds since epoch.
$ printf 'current hour is: %(%H)T:00:00\n' -1
current hour is: 17:00:00
$
$ printf 'next hour is: %(%H)T:00:00\n' $((EPOCHSECONDS + 3600))
next hour is: 18:00:00
Using awk,
$ awk ' BEGIN { st=systime();
print "current hour=" strftime("%F %H:00:00",st);
print "next hour=" strftime("%F %H:00:00",st+(60*60)) } '
current hour=2020-12-26 23:00:00
next hour=2020-12-27 00:00:00
$
my log has this date format at the beginning of each line:
2018 Sep 21 17:16:27:796
I need to grep the last 10 minutes of this log... any help?
my current experiments:
tenminutesago=$(date --date='10 minutes ago' +"%Y %b %e %H:%M:%S"):999
My idea was to convert the log format to a progressive number and then check everything greater than that number.
I see that the command: date +"%Y %b %e %H:%M:%S" gives a date in the same format of the log. The command: date +"%Y%m%e%H%M%S" gives a date in a progressive number (201810041204019)
You could do
for i in {10..0}; do
d=$(date -d "$i minutes ago" +'%Y %b %e %H:%M')
grep "$d" logfile
done
This just divides the problem in the 11 sequential subtasks of getting all lines from 10 minutes ago, all lines from 9 minutes ago, etc. until the current minute.
Edit:
Here's an alternate solution that prints all lines following the first one where a date stamp from the last 10 minutes was found, not only those that carry a date stamp, and also avoids reading the file over from start several times:
# build a regex pattern that matches any date in the given format from the last 10 minutes
pattern=$(date +'%Y %b %e %H:%M')
for i in {10..1}; do
pattern+=\|$(date -d "$i minutes ago" +'%Y %b %e %H:%M')
done
# print all lines starting from the first one that matches one of the dates in the pattern
awk "/$pattern/,0" logfile
Under the assumption that your loglines looks like
YYYY Bbb dd HH:MM:SS:sss Some random log message is here
You can do the following:
awk -v d=$(date -d "10 minutes ago" "+%Y %m %d %T") '
{ mm = sprintf("%0.2d",(index("JanFebMarAprMayJunJulAugSepOctNovDec",$2)+2)/3)
s = $1 " " mm " " $3 " "$4 }
(s >= d){print}' logfile
The idea is to convert your date format into a Sortable format (Note that "Jan" < "Mar" but "Feb" < "Jan"). This is done by converting your month into a number with two digits and then compare it stringwise against the correct date.
Try your current approach without the seconds and milliseconds.
tenminutesago=$(date --date='10 minutes ago' +"%Y %b %e %H:%M")
Is not exactly the last ten minutes to a second level, but I think it is enough for most of the cases. That will give you the first line in the log within the time window. Now you can get the total lines and subtract the line number of your previous grep, and then tail the file. The script could be like this:
LOGFILE="filename.log"
tenminutesago=$(date --date='9000 minutes ago' +"%Y %b %e %H:%M") # matching pattern
tlines=$(cat $LOGFILE | wc -l) # Total lines in file
let lines=$tlines-$(grep -n "$tenminutesago" $LOGFILE | grep -m 1 -oP "^[0-9]*" || echo $tlines) # lines after matching occurence
echo "$lines lines FOUND from the last X minutes"
tail -n $lines $LOGFILE # last lines in file
As suggested by #Gem Taylor, this could be reduced using +N option in tail.
LOGFILE="filename.log"
tenminutesago=$(date --date='9000 minutes ago' +"%Y %b %e %H:%M") # matching pattern
lines=$(grep -n "$tenminutesago" $LOGFILE | grep -m 1 -oP "^[0-9]*" || echo "0") # lines after matching occurence
echo "$lines lines FOUND from the last X minutes"
let lines -eq 0 && tail -n +$lines $LOGFILE # last lines in file if lines is not 0
hi I want to get the week number of the current month in bash, has someone an idea on how to do this? I search the date option, there is noting for week number only absolute week number.
WEEK => current week of month eg. today 22.05 WEEK=4
I found a few options, but there is no option, which works for every month and every date some give error if leading 0 some if month is even.
Here is a solution:
this_month=$(ncal -w | tail -1 | awk '{print NF}')
total_this_month=$(ncal -w | tail -1 | awk '{print $NF}')
this_week=$(date +%W)
this_monthweek=$(($this_week - $total_this_month + $this_month))
echo -e "today $(date +%d.%m) WEEK=$this_monthweek"
Hope, this is what you are looking for.
Edit:
A solution without ncal
this_month=$(date -d "20170501" +%V)
end_this_month=$(date -d "20170531" +%V)
total_this_month=$(($end_this_month - $this_month + 1))
this_week=$(date +%W)
this_monthweek=$(($this_week - $end_this_month + $total_this_month))
echo -e "today $(date +%d.%m) WEEK=$this_monthweek"
I found this solution working with AIX, but it works on any Unix
#!/bin/bash
year=$(date +'%Y')
month=$(date +'%m')
day=$(date +'%e' | tr -d '[:blank:]')
WEEKNUM=$(cal ${month} ${year} | grep -v "[[:alpha:]]" | grep -nw ${day} | cut -f1 -d':')
echo "WEEKNUM ${WEEKNUM}"
On Linux you can switch first day of the week to fit your needs
On AIX, first day of the week is inherited by locale
I figured something out, but I am not sure if it works for every month and week of the year, and I have not idea on how to manipulate the date to test it
current_week="$(date +%V)"
last_of_month="$(date --date "-"$(date +%d)" days +1 month" +%Y-%m-%d)"
last_of_month_week="$(date --date="${last_of_month}" +%V)"
week_number="$((${current_week} - ${last_of_month_week} + 5))"
I have a file with date '2015-06-01-12', how can I get it to increment the hour in shell script? The result I want is '2015-06-01-13'. If its the 23rd hour it has to move forward a date and get 00 as hour.
I was able to do it to date but have so far had not any luck with incrementing hours.
currDate=2015-06-02
nextDate=`date '+%Y-%m-%d' -d "$currDate+1 days"`
echo $nextDate
It is reasonably easy if you keep your date as an epoch (number of seconds since January 1, 1970):
$ currDate=$( date +%s -d "2015-06-02 23:00:00" )
$ echo $currDate
1433300400
$ date +%Y-%m-%d-%H -d #$currDate
2015-06-02-23
$ nextDate=$(( $currDate + 3600 )) #adding an hour's worth of seconds
$ date +%Y-%m-%d-%H -d #$nextDate
2015-06-03-00
Using the GNU date command line utility, I know:
how to substract 3 days from any given date:
date -d "20110405 -3 days" "+%Y%m%d"
20110402
how to get the last Friday from today:
date -d "last friday" "+%Y%m%d"
20110408
But I don't know how to get the last Friday from any given date:
date -d "20110405 last friday" "+%Y%m%d"
Simply returns the given date:
20110405
Any ideas on how to do this? If a one-liner is not possible a few lines of script would also be helpful.
Ugly, but one line:
date -d "20110405 -2 days -$(date -d '20110405' '+%w') days" "+%Y%m%d"
EDIT: See comments.
date -d "20110405 -$(date -d "20110405 +2 days" +%u) days" "+%Y%m%d"
Explanation:
%w returns day of the week. Friday = 5 so take off 2 more days to get the right offset.
Works out as "20110405 -x days", where x is the number of days back to last Friday.
I don't like that it repeats the date string, but hopefully it goes some way to helping.
Script example (based on the accepted answer)
DT="20170601"
# get the Friday before $DT
# expected value is 20170526
date -d "$DT -`date -d "$DT +2 days" +%u` days" "+%Y%m%d"
Further examples, using undocumented features of GNU date (from unix.com)
# assign a value to the variable DT for the examples below
DT="2006-10-01 06:55:55"
echo $DT
# add 2 days, one hour and 5 sec to any date
date --date "$DT 2 days 1 hour 5 sec"
# subtract from any date
date --date "$DT 3 days 5 hours 10 sec ago"
date --date "$DT -3 days -5 hours -10 sec"
# or any mix of +/-. What will be the date in 3 months less 5 days?
date --date "now +3 months -5 days"