Calculating days passed - stata

I have a variable date like this:
I want to calculate how many days have passed since, say, Jan 1 of 1960.
However, this is tedious. Also in some years, February has 28 days.
What I've been trying is basically looking up every single calendar, calculate how many days are there in each year, recognize string like jan as month variable 1 and so on.
Is there any short and efficient way to do this?

You need to use the daily() or date() function:
display date("1/1/2012", "DMY") - date("1/1/1960", "DMY")
18993
More generally, if you have a string variable with dates:
clear
input str10 date1
"01/01/2012"
"01/01/2011"
"01/01/2014"
"19/12/2014"
end
generate date2 = date(date, "DMY") - date("1/1/1960", "DMY")
list
+--------------------+
| date1 date2 |
|--------------------|
1. | 01/01/2012 18993 |
2. | 01/01/2011 18628 |
3. | 01/01/2014 19724 |
4. | 19/12/2014 20076 |
+--------------------+
If the variable containing the dates is numeric:
clear
input date1
18993
18628
19724
20076
end
format %tdDD/NN/CCYY date1
generate date2 = date1 - date("1/1/1960", "DMY")

Related

Create Custom Definition of Week

I have daily data and want to convert them to weekly, using the following definition. Every Monday denotes the beginning of week i, and Sunday denotes the end of week i.
My date variable is called day and is already has %td format. I have a feeling that I should use the dow() function, combined with egen, group() but I struggle to get it quite right.
If your data are once a week and you have data for Mondays only, then your date variable is fine and all you need to do is declare delta(7) if you use tsset or xtset.
If your data are for two or more days a week and you wish to collapse or contract to weekly data, then you can convert to a suitable time basis like this:
* Example generated by -dataex-. To install: ssc install dataex
clear
input float date
22067
22068
22069
22070
22071
22072
22073
22074
22075
22076
22077
22078
22079
22080
end
format %td date
gen wdate = cond(dow(date) == 1, date, cond(dow(date) == 0, date - 6, date - dow(date) + 1))
format wdate %td
gen dow = dow(date)
list, sepby(wdate)
+-----------------------------+
| date dow wdate |
|-----------------------------|
1. | 01jun2020 1 01jun2020 |
2. | 02jun2020 2 01jun2020 |
3. | 03jun2020 3 01jun2020 |
4. | 04jun2020 4 01jun2020 |
5. | 05jun2020 5 01jun2020 |
6. | 06jun2020 6 01jun2020 |
7. | 07jun2020 0 01jun2020 |
|-----------------------------|
8. | 08jun2020 1 08jun2020 |
9. | 09jun2020 2 08jun2020 |
10. | 10jun2020 3 08jun2020 |
11. | 11jun2020 4 08jun2020 |
12. | 12jun2020 5 08jun2020 |
13. | 13jun2020 6 08jun2020 |
14. | 14jun2020 0 08jun2020 |
+-----------------------------+
In short, index weeks by the Mondays that start them. Now collapse or contract your dataset. Naturally if you have panel or longitudinal data some identifier may be involved too. delta(7) remains essential for anything depending on tsset or xtset.
There is no harm in using egen to map to successive integers, but no advantage in that either.
A theme underlying this is that Stata's own weeks are idiosyncratic, always starting week 1 on 1 January and always having 8 or 9 days in week 52. For more on weeks in Stata, see the papers here and here, which include the advice given in this answer, and much more.

How do I convert (daily) date to month date?

In Stata, how do I convert date in the form of:
09mar2005 00:00:00
to a month-year variable?
If it matters, the date format is %tc.
What I have in mind is to plot monthly averages (instead of the daily average I have) of variables across time.
To get where you are now, you or somebody else may have done something like this:
clear
set obs 1
gen earlier = "09mar2005 00:00:00"
gen double nowhave = clock(earlier, "DMY hms")
format nowhave %tc
list
+-----------------------------------------+
| earlier nowhave |
|-----------------------------------------|
1. | 09mar2005 00:00:00 09mar2005 00:00:00 |
+-----------------------------------------+
Note that a string date and a numeric date-time variable with appropriate date-time format %tc just look the same when you list them, but they are quite different beasts.
To get where you want to be -- with a monthly date -- you convert from clock (date-time) to daily to monthly:
gen mdate = mofd(dofc(nowhave))
format mdate %tm
list
+--------------------------------------------------+
| earlier nowhave mdate |
|--------------------------------------------------|
1. | 09mar2005 00:00:00 09mar2005 00:00:00 2005m3 |
+--------------------------------------------------+
All is documented at help datetime. The function names stand for month of daily date and daily date of clock.

Calculating average NETWORK days Power BI

I've been reading various threads and guides to performing a 'NETWORKDAYS' style calculation in Power BI but struggling to make it work.
I have a table like this:
Team | Meeting | Report
aaa | 1/1/2018 | 9/1/2018
aaa | 1/1/2018 | 7/1/2018
bbb | 1/1/2018 | 1/2/2018
bbb | 1/1/2018 |
ccc | 1/1/2018 | 3/3/2018
aaa | 1/1/2018 |
And I want to return the average days without weekends and holidays, something like this:
Team | average
aaa | 5 (10/2)
bbb | 23 (45/1)
ccc | 45 (45/1)
I have this function, which seems to work albeit clunkily, but I don't know how to remove the non-weekdays from the Date table:
AVERAGEX(FILTER(Planning,NOT(ISBLANK(Planning Actual_FinalReport]))),
(COUNTROWS(DATESBETWEEN(DateTable[Date],
Planning[Actual_ClosingMeeting],Planning [Actual_FinalReport]))
))
Where DateTable is:
Date | Weekday
5/1/2018| 1
6/1/2018| 0
7/1/2018| 0
and so on...
Essentially, I want to iterate over Planning (filtering out blanks in [Report]) and count the dates between Meeting and Report from the Dates table, filtered by Weekday = 1. It's the syntax to link the tables I think I'm struggling with.
Modifying your formula a bit, how about something like this?
Average = AVERAGEX(
FILTER(Planning,
NOT(ISBLANK(Planning[Actual_FinalReport]))),
COUNTROWS(
FILTER(DateTable,
DateTable[Date] IN DATESBETWEEN(
DateTable[Date],
Planning[Actual_ClosingMeeting],
Planning[Actual_FinalReport]) &&
DateTable[Weekday] = 1)))
I'm adding the Weekday filter at the end.

Destringing variables

I have a data set that has data sorted by months and years. I want to destring the month variable so that I can ultimately create one date variable, but as they are all labeled as January, February, etc. how do I destring the variable?
You don't. That's a job for date functions. All are documented, e.g. via help datetime.
destring is for numbers that happen to be read as string variables so that typical entries might be "42" and "666". Import as string usually arises when the variable includes metadata (e.g. header lines), or non-Stata flags for missings (e.g. "NA"), or some other non-numeric characters, often in as few as one observation. Import from MS Excel is a common cause, as spreadsheet users tend to be loose on sprinkling text in numeric data columns.
A variable with values such as "January" doesn't qualify. It's in your mind that month names map on to month numbers, but destring doesn't share that knowledge.
Date functions have this job:
* Example generated by -dataex-. To install: ssc install dataex
clear
input str8 month float year
"January" 2017
"February" 1942
end
gen mdate = monthly(month + string(year), "MY")
list
+-------------------------+
| month year mdate |
|-------------------------|
1. | January 2017 684 |
2. | February 1942 -215 |
+-------------------------+
format mdate %tm
list
+--------------------------+
| month year mdate |
|--------------------------|
1. | January 2017 2017m1 |
2. | February 1942 1942m2 |
+--------------------------+
(Declaration of interest: original author of destring.)
See also this thread.

Stata: Aggregating by week

I have a dataset that has a date variable with missing dates.
var1
15sep2014
15sep2014
17sep2014
18sep2014
22sep2014
22sep2014
22sep2014
29sep2014
06oct2014
I aggregated the data using this command.
gen week = week(var1)
and the results look like this
var 1 week
15sep2014 37
15sep2014 37
17sep2014 38
18sep2014 38
22sep2014 38
I was wondering whether it would be possible to get the month name and year in the week variable.
In general, week() is part of the solution if and only if you define your weeks according to Stata's rules for weeks. They are
Week 1 of the year starts on January 1, regardless.
Week 2 of the year starts on January 8, regardless.
And so on, except that week 52 of the year includes 8 or 9 days, depending on
whether the year is leap or not.
Do you use these rules? I guess not. Then the simplest practice is to define a week by whichever day starts the week. If your weeks start on Sundays, then use the rule (dailydate - dow(dailydate)). If your weeks start on Mondays, ..., Saturdays, adjust the definition.
. clear
. input str9 svar1
svar1
1. "15sep2014"
2. "15sep2014"
3. "17sep2014"
4. "18sep2014"
5. "22sep2014"
6. "22sep2014"
7. "22sep2014"
8. "29sep2014"
9. "06oct2014"
10. end
. gen var1 = daily(svar1, "DMY")
. gen week = var1 - dow(var1)
. format week var1 %td
. list
+-----------------------------------+
| svar1 var1 week |
|-----------------------------------|
1. | 15sep2014 15sep2014 14sep2014 |
2. | 15sep2014 15sep2014 14sep2014 |
3. | 17sep2014 17sep2014 14sep2014 |
4. | 18sep2014 18sep2014 14sep2014 |
5. | 22sep2014 22sep2014 21sep2014 |
|-----------------------------------|
6. | 22sep2014 22sep2014 21sep2014 |
7. | 22sep2014 22sep2014 21sep2014 |
8. | 29sep2014 29sep2014 28sep2014 |
9. | 06oct2014 06oct2014 05oct2014 |
+-----------------------------------+
Much more discussion here, here and here, although the first should be sufficient.
Instead of using the week() function, I would probably use the wofd() function to transform your %td daily date into a %tw weekly date. Then you can just play with the datetime display formats to decide exactly how to format the date. For example:
gen date_weekly = wofd(var1)
format date_weekly %twww:_Mon_ccYY
That code should give you this:
var1 date_weekly
15sep2014 37: Sep 2014
15sep2014 37: Sep 2014
17sep2014 38: Sep 2014
18sep2014 38: Sep 2014
22sep2014 38: Sep 2014
This help file will be useful:
help datetime display formats
And if you want to brush up on the difference between %tw and %td dates, you might refresh yourself here:
help datetime