New date and time functions
Dates and times (or datetimes) are all too familiar concepts we often take for granted. They lurk under data management and statistical analysis (and the underlying computer system) with various degrees of importance depending on the task at hand. Sometimes, they can get tricky, and the quirks of calendars and clocks have to be dealt with.
For example, when do leaplings (persons born on February 29) celebrate their birthdays in nonleap years? And when is a year a leap year? It is not just every four years. What is the difference, say, in milliseconds, between two timestamps if leap seconds are counted, based on Coordinated Universal Time (UTC) standards?
We added a set of datetime functions, in both Stata and Mata, to accurately and conveniently handle datetimes for (1) calculating durations, such as age and other datetime differences; (2) finding relative dates, such as the next birthday after a given date; and (3) extracting components of Stata datetime values and variables.
Let’s see it work
If you were born on February 29, you age up on March 1 in UK but on February 28 in Taiwan–in nonleap years, of course. The renewal of driver’s licenses or the penalty for prematurely hitting the bar will be determined accordingly. The new function age() tells you the age, in integers, with an optional argument for handling leaplings. For example, if you were born on the leap day of 2000, the following tells you that you are still 17 at the end of February 2018 because March 1 is your birthday in nonleap years.
. display age(td(29feb2000), td(28feb2018), "01mar")
Note: td() is a function that conveniently makes Stata understand literal dates.
We do not provide the option for leaplings to celebrate their birthdays only every four years, considering the terrible ramifications, like the cruel fate of leapling Frederic in the comic opera Pirates of Penzance, who had to wait 63 years to unite with his love on his “twenty-first birthday” (Sullivan 1923).
The function datediff() calculates differences between dates in general, rounded down to the nearest integer, in various time units: year, month, or day. age() is a special case of datediff() in years. For example, if you tied the knot on July 31, 2000, you may save the day with the knowledge you have been married for 3,652 days on your 10th wedding anniversary.
. display datediff(td(31jul2000), td(31jul2010), "day")
Insurance companies may want to know the details of a person’s age, with every decimal place in age translating into dollars. Functions age_frac() and datediff_frac() find, with precise fractions, the age, and in general, the difference in dates in units of year, month, or day.
If you would like to calculate the precise number of months, say, for long-term monthly rental billing, Stata will find out whether the years in consideration have 365 or 366 days, and whether months have 28, 29, 30, or 31 days, and calculate the difference, as precisely as it gets. For example,
. display datediff_frac(td(17nov2019), today(), "month")
tells the precise number of months from the day of the first documented case of COVID-19 until today. Calculating date differences accurately can be important in survival models. datediff_frac() and age() calculate differences in a compatible manner. So if you use datetimes from datediff_frac() in a survival model and use ages from age() as predictors in the model, they will be consistent.
We generally trust that our clocks synchronize perfectly with the motion of the earth, but it does not always run like clockwork. Every year or so since 1972, a leap second is added to align our clocks with the slowdown of the earth’s rotation. There is debate about the utility of leap seconds, so at Stata we bookkeep both, that is, time with and without leap seconds. In function names, we use C for the former and c for the latter.
Function isleapsecond() tells you, as you might have guessed, whether the time in question is a leap second or not. This can be handy to let you know if there are those rare leap seconds in your data and what functions can be safely used.
Functions Clockdiff() and clockdiff() find the difference between two times, rounded down to the nearest integer, in any unit of your choice, with and without leap seconds, respectively. Clockdiff_frac() and clockdiff_frac() find this difference more precisely. If you recorded timestamps (with leap seconds) when celestial objects begin and end a complete orbit (as Stata variables begin and end), this will generate the orbital periods in days.
. generate double period = Clockdiff_frac(begin, end, "day")
We all understand strings like “July 4, 1776”. But Stata needs a more flexible representation that allows, for instance, to calculate differences. Stata actually keep dates as numbers–the number of days relative to a reference point we chose: January 1, 1960. For times, it is the number of milliseconds from the stroke of midnight on January 1, 1960.
We do not expect users to add or subtract these incomprehensible numbers, but we make it possible to calculate Stata dates, relative to other dates. We now handle birthdays relative to a given date, and dates relative to the month of a given date.
The function birthday() tells you the birthday, as a Stata date, in a given year. previousbirthday() and nextbirthday() return Stata dates for the previous and next birthday, respectively, relative to a given date.
The functions daysinmonth(), firstdayofmonth(), and lastdayofmonth() first find the month of a given Stata date and return, respectively, the number of days in that month, the Stata date for the first day in that month and the Stata date for the last day in that month.
The pesky leap day shows up approximately every four years since 1582, when Pope Gregory XIII established the now widely used Gregorian calendar by adjusting the Julian calendar (Pope Gregory XIII, 1582). The modification addressed the incorrect assumption that the average year lasts exactly 365.25 days and made sure that Easter happens closer to when it should, that is, on the March equinox. The Gregorian calendar reformed the Julian calendar by dropping leap years in century years that weren’t exactly divisible by 400.
The functions isleapyear(), previousleapyear(), and nextleapyear() take a year as input and are painfully obvious as to what they do.
We provide three generic functions, datepart(), Clockpart(), and clockpart(), that return the (integer) components of Stata datetime values and variables: year, month, day, hour, minute, second, or millisecond. Clockpart() works only with datetimes with leap seconds, and clockpart() without.
And yes, Stata now also tells the time now, with now(), and today’s date with today().