I've been recently asked to do a simple exercice to calculate the difference between 2 dates.
first date is the birth date, second date is the actual date (or any date entered as the end date) let's call it "end date".
Format: Year, Month, Day (we don't care about hours for now)
Here is the deal :
The birth date : 2021, 02, 11
The end date : 2022, 02, 10
The difference between these 2 dates is : 11 months and 30 days. That's seems the logic answer but let's try to get a little bit deeper :
11/02 -> 11/03 = 1 month : 17 + 11 = 28 }
11/03 -> 11/04 = 1 month : 20 + 11 = 31 |
11/04 -> 11/05 = 1 month : 19 + 11 = 30 |
11/05 -> 11/06 = 1 month : 20 + 11 = 31 | From February
11/06 -> 11/07 = 1 month : 19 + 11 = 30 | To January
11/07 -> 11/08 = 1 month : 20 + 11 = 31 | 11 months
11/08 -> 11/09 = 1 month : 20 + 11 = 31 | => 334 days
11/09 -> 11/10 = 1 month : 19 + 11 = 30 |
11/10 -> 11/11 = 1 month : 20 + 11 = 31 |
11/11 -> 11/12 = 1 month : 19 + 11 = 30 |
11/12 -> 11/01 = 1 month : 20 + 11 = 31 }
11/01 -> 10/02 ------------> 20 + 10 = 30
This is the reasoning behind the 11 months and 30 days, but there is another approach (correct me if I'm wrong) which is :
the starting stays the same, which is 11/02 so the rest is :
02/2021: 17/28
03/2021: 31/31 }
04/2021: 30/30 |
05/2021: 31/31 |
06/2021: 30/30 |
07/2021: 31/31 |
08/2021: 31/31 | 11 months
09/2021: 30/30 | => 337 days
10/2021: 31/31 |
11/2021: 30/30 |
12/2021: 31/31 |
01/2022: 31/31 }
02/2022: 10/28
There is a difference of 3 days between the 2 dates when using the 2nd approach, and therefore the difference will be
11 month and 27 days.
Which approach do you think is the right one ?
Related
I'm trying to come up with something to Sync weekdays between years
So far I can do it for a 4 year gap just by subtracting 364 days
For example
Monday Feb 1 2021 - 364 days becomes Monday Feb 3rd 2020
Friday Feb 19 2021 - 364 days becomes Friday Feb 21nd 2020
Tuesday Mar 2 2021 - 364 days becomes Tuesday Mar 3rd 2020
notice how the weekday is in perfect sync (Monday to Monday, Tuesday to Tuesday etc)
and I can do this for 2 years just by using 728 days (364 * 2)
and so on for 3 and 4 years
my problem is after 4 years it stops working
if I do the same thing for 5 Years (364*5)
Monday Feb 1st 2021 becomes Monday Feb 8th 2016
however I would want it to be Monday Feb 1st 2016
I cant seem to crack how to deal with this for 5 years on
This is using Zeller’s Rule to get the day number, and then just modifying the actual date when subtracting 365 days to get the day name to match. I'm sure there are edge cases (e.g. I believe this would currently allow a result of something like "March 33"), but this should get you started:
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const months = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
const dayNum = (day, month, year) => {
if (month <= 2) {
year--;
month += 12;
}
month-=2;
const lastTwoDigitsOfYear = year % 100;
const firstTwoDigitsOfYear = (year - lastTwoDigitsOfYear) / 100
let F = day + Math.floor((13*month-1)/5) + lastTwoDigitsOfYear + Math.floor(lastTwoDigitsOfYear/4) +Math.floor(firstTwoDigitsOfYear/4)-2*firstTwoDigitsOfYear
let f = F >= 0 ? (F % 7) : 7 + (F % 7);
return f
}
// Ok, so we can get the day for any date.
const syncedYearAdd = (day, month, year, numYears) => {
const d1 = dayNum(day, month, year);
const d2 = dayNum(day, month, year + numYears);
if (d1 < d2) {
day -= (d2 - d1)
} else if (d1 > d2) {
day += (d1 - d2);
}
if (day < 0) {
day += 7;
}
console.log(days[d1], day, months[month-1], year + numYears)
}
// Monday Feb 1st 2021
for (let i = 0; i <= 5; i++) {
syncedYearAdd(1, 2, 2021, i * -1)
}
I'm trying to use the following code but it gives error
01jan1986
05jan2001
07mar1983
and so on I need to get the exact age of them
gen agecat=1
if age 0-20==1
if age 21-40==2
if age 41-60==3
if age 61-64==4```
Here's one way:
gen age_cat = cond(age <= 20, 1, cond(age <= 40, 2, cond(age <= 60, 3, cond(age <= 64, 4, .))))
You might also want to look into egen, cut, see help egen.
To build off of Wouter's answer, you could do something like this to calculate the age to the tenth of a year:
clear
set obs 12
set seed 12352
global today = date("18Jun2021", "DMY")
* Sample Data
gen dob = runiformint(0,17000) // random Dates
format dob %td
* Create Age
gen age = round((ym(year(${today}),month(${today})) - ym(year(dob), month(dob)))/ 12,0.1)
* Correct age if dob in current month, but after today's date
replace age = age - 0.1 if (month(${today}) == month(dob)) & (day(dob) > day(${today}))
* age category
gen age_cat = cond(age <= 20, 1, cond(age <= 40, 2, cond(age <= 60, 3, cond(age <= 64, 4, .))))
The penultimate step is important as it decrements the age if their DOB is in the same month as the comparison date but has yet to be realised.
+----------------------------+
| dob age age_cat |
|----------------------------|
1. | 30jan2004 17.4 1 |
2. | 14aug1998 22.8 2 |
3. | 06aug1998 22.8 2 |
4. | 31aug1994 26.8 2 |
5. | 27mar1990 31.3 2 |
|----------------------------|
6. | 12jun1968 53 3 |
7. | 05may1964 57.1 3 |
8. | 06aug1994 26.8 2 |
9. | 21jun1989 31.9 2 |
10. | 10aug1984 36.8 2 |
|----------------------------|
11. | 22oct2001 19.7 1 |
12. | 03may1972 49.1 3 |
+----------------------------+
Note that the decimal is just approximate as it uses the month of the birthday and not the actual date.
You got some good advice in other answers, but this can be as simple as you want.
Consider this example, noting that presenting data as code we can run is a really helpful detail.
* Example generated by -dataex-. For more info, type help dataex
clear
input str9 sdate float dob
"01jan1986" 9497
"05jan2001" 14980
"07mar1983" 8466
end
format %td dob
The age at end 2020 is just 2020 minus the year people were born. Use any other year if it makes more sense.
. gen age = 2020 - year(dob)
. l
+-----------------------------+
| sdate dob age |
|-----------------------------|
1. | 01jan1986 01jan1986 34 |
2. | 05jan2001 05jan2001 19 |
3. | 07mar1983 07mar1983 37 |
+-----------------------------+
For 20 year bins, why not make them self-describing. Thus with this code, 20, 40 etc. are the upper limit of each bin. (You might need to tweak that if you have children under 1 year old in your data.)
. gen age2 = 20 * ceil(age/20)
. l
+------------------------------------+
| sdate dob age age2 |
|------------------------------------|
1. | 01jan1986 01jan1986 34 40 |
2. | 05jan2001 05jan2001 19 20 |
3. | 07mar1983 07mar1983 37 40 |
+------------------------------------+
This paper is a review of rounding and binning using Stata.
i have this quiz, you should make an output like this, and i search youtube tutorials for "for golang" and it explain that it has 2 style of for in golang,
1
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
2
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
3
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
4
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
5
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
it should be vertically outputted, not horizontally, so i build 3 variable, i = 1, j = 21, and k = 11, and i use for to automatically increase the value, the 1st style worked, but the 2nd style somehow its different
yt vid : https://www.youtube.com/watch?v=jZ-llP_yKNo on 5:28 min he explain that for has 2 style
1st style :
for i:=1; i <= 5; i++{
fmt.Println(i)
for j:=21; j <= 24; j++ {
println(j)
for k:=11; k<=14; k++ {
fmt.Println(k)
}
}
}
2nd style :
i:=1
j:=21
k:=11
for i <= 5{
fmt.Println(i)
i++
for j <= 24 {
println(j)
j++
for k<=14 {
fmt.Println(k)
k++
}
}
}
It's not about the syntax but about your logic.
In the 1st style with for i := ..., whenever next loop run, you reset the value to the init state, means it always sets j to 21 and k to 11. So there will a many sub loop runs.
In contrast, 2nd style, you init value j and k right before going to loop. So in the second loop of i, j and k are still the same value with 25 and 15 in that order.
There are multiple options to print the output in the golang.
fmt.Println appends a new line in the end.
fmt.Printf prints content as it is.
For more details read the documentation.
for i := 1; i <= 5; i++ {
fmt.Printf("%v ", i)
for j := 21; j <= 24; j++ {
fmt.Printf("%v ", j)
for k := 11; k <= 14; k++ {
fmt.Printf("%v ", k)
}
}
}
Output
1 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 2 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 3 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 4 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 5 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14
To add a new line use the \n escape sequence.
Check the running code link
I have this table:
Year
Month
Agency
Value
2019
9
1
233
2019
9
4
132
2019
8
3
342
2020
3
2
321
2020
3
4
34
2020
5
2
56
2020
5
4
221
2020
5
1
117
2018
12
2
112
2018
12
2
411
2020
4
3
241
2020
4
2
155
I'd like to set a new measure/column where last month from last year is 1, and 0 in another cases:
Year
Month
Agency
Value
Filter
2019
9
1
233
0
2019
9
4
132
0
2019
8
3
342
0
2020
3
2
321
0
2020
3
4
34
0
2020
5
2
56
1
2020
5
4
221
1
2020
5
1
117
1
2018
12
2
112
0
2018
12
2
411
0
2020
4
3
241
0
2020
4
2
155
0
I've been able to "copy" a new table with values from Month=5 and Year=2020 ("the lastest from the lastest"):
TableData - Last Charge =
var table = FILTER(
TableData,
AND(
MAX('TableData '[Year])='TableData '[Year],
MAX('TableData '[Month])='TableData '[Month]
)
)
return SUMMARIZE(table , TableData [Year], TableData [Month], TableData [Agency], TableData [Value])
However, my intention is don't create new tables and use measures/columns tu use it like FILTER when I create a graphic.
Thanks a lot, and sorry for my poor english.
I solved it with this measure:
Measure =
VAR a =
MAX ( 'Table'[Year] )
VAR b =
MAX ( 'Table'[Months] )
VAR c =
MAXX ( ALL ( 'Table' ), [Year] )
VAR d =
MAXX ( FILTER ( ALL ( 'Table' ), [Year] = c ), [Months] )
RETURN
IF ( a * 100 + b = c * 100 + d, 1, 0 )
d
The above 'd' is a data frame which outputs the following table containing
14 obs and 2 vars.
NUMBER DATE
1 20 2017-01-01
2 30 2017-01-02
3 40 2017-01-03
4 40 2017-01-04
5 50 2017-01-05
6 50 2017-01-06
7 60 2017-01-07
8 20 2017-01-08
9 30 2017-01-09
10 40 2017-01-10
11 40 2017-01-11
12 50 2017-01-12
13 50 2017-01-13
14 60 2017-01-14
After running the following code:
a<-c(0,7)
for(i in a){
w <- subset(d, DATE >= as.Date("2017-01-01")+a & DATE <= as.Date("2017-01-
07")+a )
print(w)
}
I get the following output. I was expecting the output to be two tables with the first dates 1st-7th and the second 8th-14. If i change the 'a' variable in the code to just '0' or just '7' it will run the dates as i'd expect (but obviously only 1 table each time i run the for loop).
NUMBER DATE
1 20 2017-01-01
3 40 2017-01-03
5 50 2017-01-05
7 60 2017-01-07
8 20 2017-01-08
10 40 2017-01-10
12 50 2017-01-12
14 60 2017-01-14
NUMBER DATE
1 20 2017-01-01
3 40 2017-01-03
5 50 2017-01-05
7 60 2017-01-07
8 20 2017-01-08
10 40 2017-01-10
12 50 2017-01-12
14 60 2017-01-14
So how do i get the output to show table 1: 1st-7th dates and table 2: 8th-14th dates?
I realise my error now. I was using 'a' instead of 'i' within the for loop.