This question already has answers here:
Get last day in month of time.Time
(4 answers)
Closed 5 months ago.
How to list the number of the days in the current date/month? Exp: January have 31 day so 1 2 3 4 till 31
Keep things simple.
The Go time package normalizes dates:
The month, day, hour, min, sec, and nsec values may be outside their usual ranges and will be normalized during the conversion. For example, October 32 converts to November 1.
For the number of days in a month
func DaysInMonth(t time.Time) int {
y, m, _ := t.Date()
return time.Date(y, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
}
For a list of days in a month
func ListDaysInMonth(t time.Time) []int {
days := make([]int, DaysInMonth(t))
for i := range days {
days[i] = i + 1
}
return days
}
The days in a month always range from 1 to the number of days in the given month. So the main task is to determine the number of days in a given month.
The time package does not expose such functionality, but you may use the following trick:
// Max days in year y1, month M1
t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC)
daysInMonth := 32 - t.Day()
The logic behind this is that the day 32 is bigger than the max day in any month. It will get automatically normalized (extra days rolled to the next month and day decremented properly). And when we subtract day we have after normalization from 32, we get exactly what the last day was in the month.
This snippet is taken from the answer time.Since() with months and years.
So here's a little helper that returns the days of a month as []int for a given time.Time:
func daysInMonth(t time.Time) []int {
t = time.Date(t.Year(), t.Month(), 32, 0, 0, 0, 0, time.UTC)
daysInMonth := 32 - t.Day()
days := make([]int, daysInMonth)
for i := range days {
days[i] = i + 1
}
return days
}
Testing it:
fmt.Println(daysInMonth(time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)))
fmt.Println(daysInMonth(time.Date(2022, 2, 1, 0, 0, 0, 0, time.UTC)))
fmt.Println(daysInMonth(time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC)))
Output (try it on the Go Playground):
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28]
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29]
Another, less peformant option is to roll back the date to the first of the month, and start adding days until the month changes. This is how it could look like:
func daysInMonth(t time.Time) []int {
var days []int
// Roll back to day 1
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC)
m := t.Month()
for t.Month() == m {
days = append(days, t.Day())
t = t.AddDate(0, 0, 1)
}
return days
}
This will output the same. Try this one on the Go Playground.
Since all months contain at least 28 days, we can optimize the above solution to roll to day 29, and start checking and incrementing from there:
func daysInMonth(t time.Time) []int {
days := make([]int, 28, 31)
for i := range days {
days[i] = i + 1
}
m := t.Month()
// Roll to day 29
t = time.Date(t.Year(), t.Month(), 29, 0, 0, 0, 0, time.UTC)
for t.Month() == m {
days = append(days, t.Day())
t = t.AddDate(0, 0, 1)
}
return days
}
Try this one on the Go Playground.
There are many ways to get it done, as we are dealing with constants mostly, and we just need to handle February if it's a Leap Year( 29 days).
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(list_of_days())
}
func list_of_days() []int {
non_leap_year := map[string]int{
"January": 31,
"February": 28,
"March": 31,
"April": 30,
"May": 31,
"June": 30,
"July": 31,
"August": 31,
"September": 30,
"October": 31,
"November": 30,
"December": 31,
}
leap_year := map[string]int{
"January": 31,
"February": 29,
"March": 31,
"April": 30,
"May": 31,
"June": 30,
"July": 31,
"August": 31,
"September": 30,
"October": 31,
"November": 30,
"December": 31,
}
//get the current month
year, month, _ := time.Now().Date()
//handle leap year
no_of_days := 0
if year%4 == 0 && year%100 != 0 || year%400 == 0 {
no_of_days = leap_year[month.String()]
} else {
no_of_days = non_leap_year[month.String()]
}
days := make([]int, no_of_days)
for i := range days {
days[i] = i + 1
}
return days
}
Not sure the best way to accomplish this.
I get these results to a text file from a mysql query. I would like to the sort 4th column with the oldest entry first.
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Wed Apr 3 17:00:52 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 14:01:05 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Fri Apr 5 13:00:56 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 08:00:59 2013 Mon Apr 8 08:00:59 2013 10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 09:00:55 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 07:00:53 2013
sort -r -k10 test does not seem to cut it.
A Perl solution using Time::Piece (in the Perl standard library since 5.10.0) and a Schwartzian Transform.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;
say map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [ $_, sortdate($_) ] } <DATA>;
sub sortdate {
my $date = join ' ', (split)[2 .. 6];
return Time::Piece->strptime($date, '%a %b %d %H:%M:%S %Y')->datetime;
}
__END__
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Wed Apr 3 17:00:52 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 14:01:05 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Fri Apr 5 13:00:56 2013 Mon Apr 15 09:42:33 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Mon Apr 8 08:00:59 2013 Mon Apr 8 08:00:59 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 09:00:55 2013
10.xxx.xxx.xxx 70:xx:xx:xx:xx:xx Thu Mar 28 14:15:12 2013 Fri Apr 5 07:00:53 2013
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
FOR /f "tokens=1-7*" %%a IN (sqlout.txt) DO (
SET "month="
FOR %%m IN (01 Jan 02 Feb 03 Mar 04 Apr 11 Nov 12 Dec) DO IF NOT DEFINED month (
IF %%d==%%m SET month=!prev!
SET prev=%%m
)
SET /a day=100+%%e
ECHO(%%g!month!!day!%%f*%%a %%b %%c %%d %%e %%f %%g %%h
)
)>tempfile.1
(
FOR /f "delims=" %%i IN ('sort tempfile.1') DO (
SET line=%%i
ECHO(!line:**=!
)
) >sortedoutput.txt
DEL tempfile.1 /F /Q
On the sample data, there are 8 significant columns. Of these, the fourth is month, fifth date, sixth time and seventh year. I have no idea what you mean by the "fourth" column being "the" date since there are two separate dates in each line.
The process simply picks up the fourth column and looks through a list of month numbers (2-digit) and month abbreviations. It's easier to save the previous element for use when the next is compared, so when the monthname matches the fourth column in %%d, the month variable is set, and that will turn off any further processing of the month.
You may have noticed I've not listed all of the months This gives you something to do. It obviously won't work unless all of the months are entered in the list.
Next we deal with the fifth column, and add 100 to the day number, producing a number from 101 to 131. These numbers all have three characters.
Next we ECHO out a string of
the year from column 7 in %%g
the 2-character month number in month
the 3-digit augmented day number
the time from column 6
an asterisk
each of the elements of the original line
Next step is to read each of those lines after sorting.
set the sorted line into line
echo everything from line except the part up to the first asterisk.
When I run
get <path>
in zookeepr CLI, I get the following
192.168.0.102
cZxid = 0x2e93
ctime = Wed Feb 06 15:12:20 GMT+05:30 2013
mZxid = 0x2e93
mtime = Wed Feb 06 15:12:20 GMT+05:30 2013
pZxid = 0x2e93
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x13cae2a97ed001f
dataLength = 13
numChildren = 0
For the same path I am trying to get the data as follow
client.getData().forPath(path);
I deserialize the data. But it is not returning anything.
I also tried
client.getData().inBackround().forPath(path);
client.getData().watched().inBackGround().forPath(path);
It's because you are using inBackground().
inBackground() causes the request to execute asynchronously. By removing inBackground() you should get the desired outcome.
Consider I have this Matrix:
02, 04, 06, 08, 10, 2
07, 14, 21, 28, 35, 2
11, 22, 33, 44, 55, 0
15, 14, 21, 28, 35, 2
I would like to have the same matrix but with only rows with last column = 2. So I want this Matrix:
02, 04, 06, 08, 10, 2
07, 14, 21, 28, 35, 2
15, 14, 21, 28, 35, 2
I could parse all matrix, but is there any other way?
Edit
To be more precise I have a cell array with strings:
02, 04, Some String, 08, 10, 2
07, 14, Some String1, 28, 35, 2
11, 22, Some String1, 44, 55, 0
15, 14, Some String, 28, 35, 2
Just use logical indexing on the rows of your matrix:
row_idx = (A(:, end) == 2);
Now row_idx contains a logical array of 1s and 0s, with 1s where the last element of the row equals 2.
Now filter these rows with:
A_filtered = A(row_idx, :);
All these steps are usually performed in a one-liner:
A_filtered = A(A(:, end) == 2, :);
I've seen this question answered in other languages but not the Korn Shell. I need to prevent a script from being run on the last business day of the month (we can assume M-F are business days, ignore holidays).
This function works in Bash, Korn shell and zsh, but it requires a date command (such as GNU date) that has the -d option:
function lbdm { typeset lbdm ldm dwn m y; (( m = $1 + 1 )); if [[ $m = 13 ]]; then m=1; (( y = $2 + 1 )); else y=$2; fi; ldm=$(date -d "$m/1/$y -1 day"); dwn=$(date -d "$ldm" +%u);if [[ $dwn = 6 || $dwn = 7 ]]; then ((offset = 5 - $dwn)); lbdm=$(date -d "$ldm $offset day"); else lbdm=$ldm; fi; echo $lbdm; }
Run it like this:
$ lbdm 10 2009
Fri Oct 30 00:00:00 CDT 2009
Here is a demo script broken into separate lines and with better variable names and some comments:
for Month in {1..12} # demo a whole year
do
Year=2009
LastBusinessDay=""
(( Month = $Month + 1 )) # use the beginning of the next month to find the end of the one we're interested in
if [[ $Month = 13 ]]
then
Month=1
(( Year++ ))
fi;
# these two calls to date could be combined and then parsed out
# this first call is in "American" order, but could be changed - everything else is localized - I think
LastDayofMonth=$(date -d "$Month/1/$Year -1 day") # get the day before the first of the month
DayofWeek=$(date -d "$LastDayofMonth" +%u) # the math is easier than Sun=0 (%w)
if [[ $DayofWeek = 6 || $DayofWeek = 7 ]] # if it's Sat or Sun
then
(( Offset = 5 - $DayofWeek )) # then make it Fri
LastBusinessDay=$(date -d "$LastDayofMonth $Offset day")
else
LastBusinessDay=$LastDayofMonth
fi
echo "$LastDayofMonth - $DayofWeek - $LastBusinessDay"
done
Output:
Sat Jan 31 00:00:00 CST 2009 - 6 - Fri Jan 30 00:00:00 CST 2009
Sat Feb 28 00:00:00 CST 2009 - 6 - Fri Feb 27 00:00:00 CST 2009
Tue Mar 31 00:00:00 CDT 2009 - 2 - Tue Mar 31 00:00:00 CDT 2009
Thu Apr 30 00:00:00 CDT 2009 - 4 - Thu Apr 30 00:00:00 CDT 2009
Sun May 31 00:00:00 CDT 2009 - 7 - Fri May 29 00:00:00 CDT 2009
Tue Jun 30 00:00:00 CDT 2009 - 2 - Tue Jun 30 00:00:00 CDT 2009
Fri Jul 31 00:00:00 CDT 2009 - 5 - Fri Jul 31 00:00:00 CDT 2009
Mon Aug 31 00:00:00 CDT 2009 - 1 - Mon Aug 31 00:00:00 CDT 2009
Wed Sep 30 00:00:00 CDT 2009 - 3 - Wed Sep 30 00:00:00 CDT 2009
Sat Oct 31 00:00:00 CDT 2009 - 6 - Fri Oct 30 00:00:00 CDT 2009
Mon Nov 30 00:00:00 CST 2009 - 1 - Mon Nov 30 00:00:00 CST 2009
Thu Dec 31 00:00:00 CST 2009 - 4 - Thu Dec 31 00:00:00 CST 2009
Note: I discovered during testing that if you try to use this for dates around World War II that it fails due to wartime time zones like CWT and CPT.
Edit: Here's a version that should run on AIX and other systems that can't use the above. It should work on Bourne, Bash, Korn and zsh.
function lbdN { cal $1 $2 | awk 'NF == 0 {next} FNR > 2 {week = $0} END {num = split(week, days); lbdN = days[num]; if ( num == 1 ) { lbdN -= 2 }; if ( num == 7 ) { lbdN-- }; print lbdN }'; }
You may have to make adjustments if your cal starts weeks on Monday.
Here's how you can use it:
month=12; year=2009 # if these are unset or null, the current month/year will be used
if [[ $(date +%d) == $(lbdN $month $year) ]];
then
echo "Don't do stuff today"
else
echo "It's not the last business day of the month"
fi
making appropriate adjustments for your shell's if...then syntax, of course.
Edit: Bug Fix: The previous version of lbdN failed when February ends on Saturday the 28th because of the way it used tail. The new version fixes that. It uses only cal and awk.
Edit: For completeness, I thought it would be handy to include functions for the first business day of the month.
Requires date with -d:
function fbdm { typeset dwn d; dwn=$(date -d "$1/1/$2" +%u); d=1; if [[ $dwn = 6 || $dwn = 7 ]]; then (( d = 9 - $dwn )); fi; echo $(date -d "$1/$d/$2"); }
For May 2010:
Mon May 3 00:00:00 CDT 2010
Requires cal and awk only:
function fbdN { cal $1 $2 | awk 'FNR == 3 { week = $0 } END { num = split(week, days); fbdN = days[1]; if ( num == 1 ) { fbdN += 2 }; if ( num == 7 ) { fbdN++ }; print fbdN }'; }
For August 2010:
2