Background
Data are often associated with a point in time, a particular
year;
month;
day;
hour, minute, second, …
Some issues with points in time:
R has data types to represent
R stores dates as days since January 1, 1970, and date-times as the
the number of seconds since midnight on that day in Coordinated
Universal Time (UTC) .
Date objects are less complicated than data-time objects, so if you
only need dates you should stick with date objects.
Base R provides many facilities for dealing with dates and
date-times.
The lubridate package provides a useful interface.
library(lubridate)
The Dates and
Times chapter of R for
Data Science provides more details.
Creating Dates and Times
Today and Now
The lubridate function today() returns
today’s date as a Date object:
today()
## [1] "2026-04-03"
class(today())
## [1] "Date"
The lubridate function now() returns the
current date-time as a POSIXct object:
now()
## [1] "2026-04-03 13:33:57 CDT"
class(now())
## [1] "POSIXct" "POSIXt"
The printed representation follows the international standard for the
representation of dates and times (ISO8601 ).
Date and date-time objects can be used with addition and
subtraction:
now() + 3600 ## one hour from now
## [1] "2026-04-03 14:33:57 CDT"
today() - 7 ## one week ago
## [1] "2026-03-27"
Parsing Dates and Times From Strings
Some common date formats:
d1 <- "2026-04-15"
d2 <- "April 15, 2026"
d3 <- "15 April 2026"
d4 <- "15 April 26"
These can be decoded by the functions ymd(),
mdy(), and dmy():
ymd(d1)
## [1] "2026-04-15"
mdy(d2)
## [1] "2026-04-15"
dmy(d3)
## [1] "2026-04-15"
dmy(d4)
## [1] "2026-04-15"
By default, these functions use the current locale settings
for interpreting month names or abbreviations.
Sys.getlocale("LC_TIME")
## [1] "en_US.UTF-8"
If you need to parse a French date you might use
dmy("15 Avril, 2026", locale = "fr_FR.UTF-8")
## [1] "2026-04-15"
Date-times can be decoded with functions like
mdy_hm:
mdy_hm("April 15, 2026, 6:15 PM")
## [1] "2026-04-15 18:15:00 UTC"
or
mdy_hms("April 15, 2026, 6:15:08 PM")
## [1] "2026-04-15 18:15:08 UTC"
By default these assume the time is specified in the UTC time
zone.
The anytime package may be useful as well:
anytime::anydate("15 April, 2026")
## [1] "2026-04-15"
anytime::anydate("April 15, 2026")
## [1] "2026-04-15"
This package can handle mixed formats:
anytime::anydate(c("15 April, 2026", "April 15, 2026"))
## [1] "2026-04-15" "2026-04-15"
It is a little more fussy about times:
anytime::anytime("April 15, 2026, 6:15 PM")
## [1] "2026-04-15 CDT"
anytime::anytime("April 15, 2026 18:15")
## [1] "2026-04-15 18:15:00 CDT"
Creating Dates and Times from Components
Dates can be created from year, month, and day by
make_date():
make_date(2026, 4, 15)
## [1] "2026-04-15"
Creating a date variable from the year,
month, and day variables in the New York City
flights table:
library(nycflights13)
fl <- mutate(flights,
date = make_date(year, month, day))
ggplot and other graphics systems know how to make
useful axis labels for dates:
ggplot(count(fl, date)) +
geom_line(aes(x = date, y = n))
Weekday/weekend differenes are clearly visible.
Date-times can be created from year, month, day, hour, minute, and
second using make_datetime():
make_datetime(2026, 4, 15, 18, 15)
## [1] "2026-04-15 18:15:00 UTC"
An attempt to recreate the time_hour variable in the
flights table:
fl <- mutate(fl,
th = make_datetime(year, month, day,
hour))
This does not quite re-create the time_hour
variable:
identical(fl$th, fl$time_hour)
## [1] FALSE
fl$th[1]
## [1] "2013-01-01 05:00:00 UTC"
fl$time_hour[1]
## [1] "2013-01-01 05:00:00 EST"
By default, make_datetime() assumes the time points it
is given are in UTC.
The time_hour variable is using local (eastern US)
time.
We will look at time zones more later .
Date and Time Components
Components of dates and date-times can be extracted with:
year(), month(), day(),
hour(), minute(), second()
yday() – day of the year
mday() – day of the month, same as
day
wday() – day of the week
By default, wday() returns an integer:
wday(today())
## [1] 6
But it can also return a label:
wday(today(), label = TRUE)
## [1] Fri
## Levels: Sun < Mon < Tue < Wed < Thu < Fri < Sat
wday(today(), label = TRUE, abbr = FALSE)
## [1] Friday
## 7 Levels: Sunday < Monday < Tuesday < Wednesday < Thursday < ... < Saturday
Weekday names and abbreviations are obviously locale-specific, and
you can specify an alternative to the default current locale:
wday(today(), label = TRUE, abbr = FALSE, locale = "de_DE.UTF-8")
## [1] Freitag
## 7 Levels: Sonntag < Montag < Dienstag < Mittwoch < Donnerstag < ... < Samstag
wday(today(), label = TRUE, locale = "de_DE.UTF-8")
## [1] Fr
## Levels: So < Mo < Di < Mi < Do < Fr < Sa
Even the integer value can be tricky:
In the US, Canada, Japan the first day of the week is
Sunday.
In Germany, France, and the ISO8601 standard the first day of the
week is Monday.
wday() can be asked to use a different first day, and a
global default can be set.
Using wday() and the date variable we can
look at the distribution of the number of flights by day of the
week:
ggplot(fl, aes(x = wday(date, label = TRUE))) +
geom_bar(fill = "deepskyblue3")
There were substantially fewer flights on Saturdays but only slightly
fewer flights on Sundays.
Rounding
floor_date(), round_date(), and
ceiling_date() can be used to round to a particular unit;
the most useful are week and quarter.
Flights by week:
The first and last weeks were incomplete:
as.character(wday(ymd("2013-01-01"),
label = TRUE, abbr = FALSE))
## [1] "Tuesday"
as.character(wday(ymd("2013-12-31"),
label = TRUE, abbr = FALSE))
## [1] "Tuesday"
Time Spans
Subtracting dates or date-times produces difftime
objects:
now() - as_datetime(today())
## Time difference of 18.56655 hours
today() - ymd("2026-01-01")
## Time difference of 92 days
Working with different units can be awkward; lubridate
provides durations , which always work in seconds:
as.duration(now() - as_datetime(today()))
## [1] "66839.5954928398s (~18.57 hours)"
as.duration(today() - ymd("2026-01-01"))
## [1] "7948800s (~13.14 weeks)"
Durations can be created with dyears(),
ddays(), dweeks(), etc.:
dyears(1)
## [1] "31557600s (~1 years)"
ddays(1)
## [1] "86400s (~1 days)"
Durations can be added to a date or date-time object and can be
multiplied by a number:
today()
## [1] "2026-04-03"
today() + ddays(2)
## [1] "2026-04-05"
today() + 2 * ddays(1)
## [1] "2026-04-05"
(n1 <- now())
## [1] "2026-04-03 13:33:59 CDT"
n1 + dminutes(3)
## [1] "2026-04-03 13:36:59 CDT"
Duations represent an exact number of seconds, which can lead to
surprises when DST is involved.
In 2026 the switch to DST happened in the US on March 8:
ymd_hm("2026-03-07 23:02", tz = "America/Chicago") + ddays(1)
## [1] "2026-03-09 00:02:00 CDT"
Periods are an alternative that may work more
intuitively.
Periods are constructed with years(),
months(), days(), etc:
ymd_hm("2026-03-07 23:02", tz = "America/Chicago") + days(1)
## [1] "2026-03-08 23:02:00 CDT"
Time Zones
Date-time objects specify a point in time relative to second zero,
minute zero, hour zero, on January 1, 1970 in Coordinated
Universal Time (UTC) .
Date-time objects can have a time zone associated with them that
affects how they are printed.
now() returns a date-time object with the time zone set
as the local time zone of the computer.
now()
## [1] "2026-04-03 13:33:59 CDT"
Time zones are complex, they can change on a regular basis (DST) or
as a result of politics.
When a date-time object is created from components, by default it is
given the UTC time zone.
To create a point in time based on local time information, such as 10
AM on April 15, 2026, in Iowa City, a time zone for interpreting the
local time needs to be specified.
The short notations like CDT are not adequate for this: Both the US
and Australia have EST, which are quite different.
R uses the Internet
Assigned Numbers Authority (IANA) naming convention and data
base.
The local time zone is:
Sys.timezone()
## [1] "America/Chicago"
The time point 10:00:00 AM on April 15, 2026 in Iowa City can be
specified as
(tm <- make_datetime(2026, 4, 15, 10, tz = "America/Chicago"))
## [1] "2026-04-15 10:00:00 CDT"
Time zones of date-time objects can be changed in two ways:
The available time zone specifications are contained in
OlsonNames:
head(OlsonNames())
## [1] "Africa/Abidjan" "Africa/Accra" "Africa/Addis_Ababa"
## [4] "Africa/Algiers" "Africa/Asmara" "Africa/Asmera"
The instant tm in some other time zones:
with_tz(tm, tz = "UTC")
## [1] "2026-04-15 15:00:00 UTC"
with_tz(tm, tz = "America/New_York")
## [1] "2026-04-15 11:00:00 EDT"
with_tz(tm, tz = "Asia/Shanghai")
## [1] "2026-04-15 23:00:00 CST"
with_tz(tm, tz = "Pacific/Auckland")
## [1] "2026-04-16 03:00:00 NZST"
with_tz(tm, tz = "Asia/Kolkata")
## [1] "2026-04-15 20:30:00 IST"
with_tz(tm, tz = "America/St_Johns")
## [1] "2026-04-15 12:30:00 NDT"
with_tz(tm, tz = "Asia/Kathmandu")
## [1] "2026-04-15 20:45:00 +0545"
Some more examples:
## All offsets that are not a full hour:
get_offset <- function(z)
abs(minute(with_tz(tm, tz = z)) - minute(tm))
offsets <- data.frame(zone = OlsonNames()) |>
mutate(offset = sapply(zone, get_offset)) |>
arrange(offset)
filter(offsets, offset != 0)
## Offsets for Australia:
filter(offsets, grepl("Australia", zone))
If we create the th variable for the flights data as
fl <- mutate(flights, th = make_datetime(year, month, day, hour,
tz = "America/New_York"))
then the result matches the date_time variable:
identical(fl$th, fl$time_hour)
## [1] TRUE
The time_hour variable in the weather table
reflects actual points in time and, together with origin,
can serve as a primary key:
filter(count(weather, origin, time_hour), n > 1)
## # A tibble: 0 × 3
## # ℹ 3 variables: origin <chr>, time_hour <dttm>, n <int>
The month, day, hour variables
are confused by the time change.
In November there is a repeat:
count(weather, origin, month, day, hour) |>
filter(n > 1)
## # A tibble: 3 × 5
## origin month day hour n
## <chr> <int> <int> <int> <int>
## 1 EWR 11 3 1 2
## 2 JFK 11 3 1 2
## 3 LGA 11 3 1 2
and there is a missing hour in March:
select(weather, origin, month, day, hour) |>
filter(origin == "EWR", month == 3,
day == 10, hour <= 3)
## # A tibble: 3 × 4
## origin month day hour
## <chr> <int> <int> <int>
## 1 EWR 3 10 0
## 2 EWR 3 10 1
## 3 EWR 3 10 3
Things to Look Out For
For dates:
Language used for months and weekdays, and their
abbreviations.
Ambiguous numerical conventions like 4/11/2026: is this April 11
or November 4?
Day 2 of the week: is this Monday or Tuesday?
For historical data, what calendar is being used? (The
October Revolution happened on November 6/7, 1917 by the
current Gregorian calendar; October 24/25 by the Julian calendar Russia
was still using.)
For date-times
All of the above.
Daylight saving time.
Time zones.
Exercises
Using the NYC flights data, how many flights were there on
Saturdays from Newark (EWR) to Cicago O’Hare (ORD) in 2013?
413
522
601
733
What day of the week will July 4, 2030, fall on?
Monday
Wednesday
Thursday
Saturday
LS0tCnRpdGxlOiAiRGF0ZXMgYW5kIFRpbWVzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgo8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9InN0YXQ0NTgwLmNzcyIgdHlwZT0idGV4dC9jc3MiIC8+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+IC5yZW1hcmstY29kZSB7IGZvbnQtc2l6ZTogODUlOyB9IDwvc3R5bGU+CmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0Kc291cmNlKGhlcmU6OmhlcmUoInNldHVwLlIiKSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbGxhcHNlID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDYsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQoKc2V0LnNlZWQoMTIzNDUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShwYXRjaHdvcmspCnNvdXJjZShoZXJlOjpoZXJlKCJkYXRhc2V0cy5SIikpCnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKCkgKwogICAgICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImdyZXkzMCIsIGZpbGwgPSBOQSkpKQpgYGAKCgojIyBCYWNrZ3JvdW5kCgpEYXRhIGFyZSBvZnRlbiBhc3NvY2lhdGVkIHdpdGggYSBwb2ludCBpbiB0aW1lLCBhIHBhcnRpY3VsYXIKCiogeWVhcjsKCiogbW9udGg7CgoqIGRheTsKCiogaG91ciwgbWludXRlLCBzZWNvbmQsIC4uLgoKU29tZSBpc3N1ZXMgd2l0aCBwb2ludHMgaW4gdGltZToKCiogTGVhcCB5ZWFycyBhbmQgbGVhcCBzZWNvbmRzLgoKKiBEYXlsaWdodCBzYXZpbmcgdGltZS4KCiogTG9jYWwgdGltZSBvcgogIFtfQ29vcmRpbmF0ZWQgVW5pdmVyc2FsIFRpbWUKICAgICAgKFVUQylfXShodHRwczovL3d3dy50aW1lYW5kZGF0ZS5jb20vdGltZS9hYm91dHV0Yy5odG1sKS4KCiogRm9yIGhpc3RvcmljYWwgZGF0YTogY2hhbmdlcyBpbiBjYWxlbmRhcnMuCgpSIGhhcyBkYXRhIHR5cGVzIHRvIHJlcHJlc2VudAoKKiBhIHBhcnRpY3VsYXIgZGF0ZSAoYERhdGVgKTsKCiogYSBwYXJ0aWN1bGFyIHNlY29uZCAoYFBPU0lYY3RgLCBkYXRlLXRpbWUpLgoKUiBzdG9yZXMgZGF0ZXMgYXMgZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDE5NzAsIGFuZCBkYXRlLXRpbWVzIGFzIHRoZQp0aGUgbnVtYmVyIG9mIHNlY29uZHMgc2luY2UgbWlkbmlnaHQgb24gdGhhdCBkYXkgaW4KW19Db29yZGluYXRlZCBVbml2ZXJzYWwgVGltZV8KICAgIChVVEMpXShodHRwczovL3d3dy50aW1lYW5kZGF0ZS5jb20vdGltZS9hYm91dHV0Yy5odG1sKS4KCkRhdGUgb2JqZWN0cyBhcmUgbGVzcyBjb21wbGljYXRlZCB0aGFuIGRhdGEtdGltZSBvYmplY3RzLCBzbyBpZiB5b3UKb25seSBuZWVkIGRhdGVzIHlvdSBzaG91bGQgc3RpY2sgd2l0aCBkYXRlIG9iamVjdHMuCgpCYXNlIFIgcHJvdmlkZXMgbWFueSBmYWNpbGl0aWVzIGZvciBkZWFsaW5nIHdpdGggZGF0ZXMgYW5kIGRhdGUtdGltZXMuCgpUaGUgYGx1YnJpZGF0ZWAgcGFja2FnZSBwcm92aWRlcyBhIHVzZWZ1bCBpbnRlcmZhY2UuCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQpsaWJyYXJ5KGx1YnJpZGF0ZSkKYGBgCgpUaGUKW19EYXRlcyBhbmQgVGltZXNfIGNoYXB0ZXJdKGh0dHBzOi8vcjRkcy5oYWRsZXkubnovZGF0ZXRpbWVzLmh0bWwpCm9mIFtfUiBmb3IgRGF0YSBTY2llbmNlX10oaHR0cHM6Ly9yNGRzLmhhZGxleS5uei8pIHByb3ZpZGVzIG1vcmUKZGV0YWlscy4KCgojIyBDcmVhdGluZyBEYXRlcyBhbmQgVGltZXMKCgojIyMgVG9kYXkgYW5kIE5vdwoKVGhlIGBsdWJyaWRhdGVgIGZ1bmN0aW9uIGB0b2RheSgpYCByZXR1cm5zIHRvZGF5J3MgZGF0ZSBhcyBhIGBEYXRlYCBvYmplY3Q6CgpgYGB7cn0KdG9kYXkoKQpgYGAKCmBgYHtyfQpjbGFzcyh0b2RheSgpKQpgYGAKClRoZSBgbHVicmlkYXRlYCBmdW5jdGlvbiBgbm93KClgIHJldHVybnMgdGhlIGN1cnJlbnQgZGF0ZS10aW1lIGFzIGEKYFBPU0lYY3RgIG9iamVjdDoKCmBgYHtyfQpub3coKQpgYGAKCmBgYHtyfQpjbGFzcyhub3coKSkKYGBgCgpUaGUgcHJpbnRlZCByZXByZXNlbnRhdGlvbiBmb2xsb3dzIHRoZSBpbnRlcm5hdGlvbmFsIHN0YW5kYXJkIGZvciB0aGUKcmVwcmVzZW50YXRpb24gb2YgZGF0ZXMgYW5kIHRpbWVzCihbSVNPODYwMV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEpKS4KCkRhdGUgYW5kIGRhdGUtdGltZSBvYmplY3RzIGNhbiBiZSB1c2VkIHdpdGggYWRkaXRpb24gYW5kIHN1YnRyYWN0aW9uOgoKYGBge3J9Cm5vdygpICsgMzYwMCAgIyMgb25lIGhvdXIgZnJvbSBub3cKYGBgCgpgYGB7cn0KdG9kYXkoKSAtIDcgICAjIyBvbmUgd2VlayBhZ28KYGBgCgoKIyMjIFBhcnNpbmcgRGF0ZXMgYW5kIFRpbWVzIEZyb20gU3RyaW5ncwoKU29tZSBjb21tb24gZGF0ZSBmb3JtYXRzOgoKYGBge3J9CmQxIDwtICIyMDI2LTA0LTE1IgpkMiA8LSAiQXByaWwgMTUsIDIwMjYiCmQzIDwtICIxNSBBcHJpbCAyMDI2IgpkNCA8LSAiMTUgQXByaWwgMjYiCmBgYAoKVGhlc2UgY2FuIGJlIGRlY29kZWQgYnkgdGhlIGZ1bmN0aW9ucyBgeW1kKClgLCBgbWR5KClgLCBhbmQgYGRteSgpYDoKCmBgYHtyfQp5bWQoZDEpCmBgYAoKYGBge3J9Cm1keShkMikKYGBgCgpgYGB7cn0KZG15KGQzKQpgYGAKCmBgYHtyfQpkbXkoZDQpCmBgYAoKQnkgZGVmYXVsdCwgdGhlc2UgZnVuY3Rpb25zIHVzZSB0aGUgY3VycmVudCBfbG9jYWxlXyBzZXR0aW5ncyBmb3IKaW50ZXJwcmV0aW5nIG1vbnRoIG5hbWVzIG9yIGFiYnJldmlhdGlvbnMuCgpgYGB7cn0KU3lzLmdldGxvY2FsZSgiTENfVElNRSIpCmBgYAoKSWYgeW91IG5lZWQgdG8gcGFyc2UgYSBGcmVuY2ggZGF0ZSB5b3UgbWlnaHQgdXNlCgpgYGB7cn0KZG15KCIxNSBBdnJpbCwgMjAyNiIsIGxvY2FsZSA9ICJmcl9GUi5VVEYtOCIpCmBgYAoKRGF0ZS10aW1lcyBjYW4gYmUgZGVjb2RlZCB3aXRoIGZ1bmN0aW9ucyBsaWtlIGBtZHlfaG1gOgoKYGBge3J9Cm1keV9obSgiQXByaWwgMTUsIDIwMjYsIDY6MTUgUE0iKQpgYGAKCm9yCgpgYGB7cn0KbWR5X2htcygiQXByaWwgMTUsIDIwMjYsIDY6MTU6MDggUE0iKQpgYGAKCkJ5IGRlZmF1bHQgdGhlc2UgYXNzdW1lIHRoZSB0aW1lIGlzIHNwZWNpZmllZCBpbiB0aGUgVVRDIHRpbWUgem9uZS4KClRoZSBgYW55dGltZWAgcGFja2FnZSBtYXkgYmUgdXNlZnVsIGFzIHdlbGw6CgkKYGBge3J9CmFueXRpbWU6OmFueWRhdGUoIjE1IEFwcmlsLCAyMDI2IikKYW55dGltZTo6YW55ZGF0ZSgiQXByaWwgMTUsIDIwMjYiKQpgYGAKClRoaXMgcGFja2FnZSBjYW4gaGFuZGxlIG1peGVkIGZvcm1hdHM6CgpgYGB7cn0KYW55dGltZTo6YW55ZGF0ZShjKCIxNSBBcHJpbCwgMjAyNiIsICJBcHJpbCAxNSwgMjAyNiIpKQpgYGAKCkl0IGlzIGEgbGl0dGxlIG1vcmUgZnVzc3kgYWJvdXQgdGltZXM6CgpgYGB7cn0KYW55dGltZTo6YW55dGltZSgiQXByaWwgMTUsIDIwMjYsIDY6MTUgUE0iKQphbnl0aW1lOjphbnl0aW1lKCJBcHJpbCAxNSwgMjAyNiAxODoxNSIpCmBgYAoKCiMjIyBDcmVhdGluZyBEYXRlcyBhbmQgVGltZXMgZnJvbSBDb21wb25lbnRzCgpEYXRlcyBjYW4gYmUgY3JlYXRlZCBmcm9tIHllYXIsIG1vbnRoLCBhbmQgZGF5IGJ5IGBtYWtlX2RhdGUoKWA6CgpgYGB7cn0KbWFrZV9kYXRlKDIwMjYsIDQsIDE1KQpgYGAKCkNyZWF0aW5nIGEgYGRhdGVgIHZhcmlhYmxlIGZyb20gdGhlIGB5ZWFyYCwgYG1vbnRoYCwgYW5kIGBkYXlgCnZhcmlhYmxlcyBpbiB0aGUgTmV3IFlvcmsgQ2l0eSBgZmxpZ2h0c2AgdGFibGU6CgpgYGB7cn0KbGlicmFyeShueWNmbGlnaHRzMTMpCmZsIDwtIG11dGF0ZShmbGlnaHRzLAogICAgICAgICAgICAgZGF0ZSA9IG1ha2VfZGF0ZSh5ZWFyLCBtb250aCwgZGF5KSkKYGBgCgpgZ2dwbG90YCBhbmQgb3RoZXIgZ3JhcGhpY3Mgc3lzdGVtcyBrbm93IGhvdyB0byBtYWtlIHVzZWZ1bCBheGlzCmxhYmVscyBmb3IgZGF0ZXM6CgpgYGB7ciwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CmdncGxvdChjb3VudChmbCwgZGF0ZSkpICsKICAgIGdlb21fbGluZShhZXMoeCA9IGRhdGUsIHkgPSBuKSkKYGBgCgpXZWVrZGF5L3dlZWtlbmQgZGlmZmVyZW5lcyBhcmUgY2xlYXJseSB2aXNpYmxlLgoKRGF0ZS10aW1lcyBjYW4gYmUgY3JlYXRlZCBmcm9tIHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1pbnV0ZSwgYW5kIHNlY29uZAp1c2luZyBgbWFrZV9kYXRldGltZSgpYDoKCmBgYHtyfQptYWtlX2RhdGV0aW1lKDIwMjYsIDQsIDE1LCAxOCwgMTUpCmBgYAoKQW4gYXR0ZW1wdCB0byByZWNyZWF0ZSB0aGUgYHRpbWVfaG91cmAgdmFyaWFibGUgaW4gdGhlIGZsaWdodHMgdGFibGU6CgpgYGB7cn0KZmwgPC0gbXV0YXRlKGZsLAogICAgICAgICAgICAgdGggPSBtYWtlX2RhdGV0aW1lKHllYXIsIG1vbnRoLCBkYXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91cikpCmBgYAoKVGhpcyBkb2VzIG5vdCBxdWl0ZSByZS1jcmVhdGUgdGhlIGB0aW1lX2hvdXJgIHZhcmlhYmxlOgpgYGB7cn0KaWRlbnRpY2FsKGZsJHRoLCBmbCR0aW1lX2hvdXIpCmBgYAoKYGBge3J9CmZsJHRoWzFdCmZsJHRpbWVfaG91clsxXQpgYGAKCkJ5IGRlZmF1bHQsIGBtYWtlX2RhdGV0aW1lKClgIGFzc3VtZXMgdGhlIHRpbWUgcG9pbnRzIGl0IGlzIGdpdmVuIGFyZSBpbiBVVEMuCgpUaGUgYHRpbWVfaG91cmAgdmFyaWFibGUgaXMgdXNpbmcgbG9jYWwgKGVhc3Rlcm4gVVMpIHRpbWUuCgpXZSB3aWxsIGxvb2sgYXQgdGltZSB6b25lcyBtb3JlIFtsYXRlcl0oI3RpbWUtem9uZXMpLgoKCiMjIERhdGUgYW5kIFRpbWUgQ29tcG9uZW50cwoKQ29tcG9uZW50cyBvZiBkYXRlcyBhbmQgZGF0ZS10aW1lcyBjYW4gYmUgZXh0cmFjdGVkIHdpdGg6CgoqIGB5ZWFyKClgLCBgbW9udGgoKWAsIGBkYXkoKWAsIGBob3VyKClgLCBgbWludXRlKClgLCBgc2Vjb25kKClgCiogYHlkYXkoKWAgLS0gZGF5IG9mIHRoZSB5ZWFyCiogYG1kYXkoKWAgLS0gZGF5IG9mIHRoZSBtb250aCwgc2FtZSBhcyBgZGF5YAoqIGB3ZGF5KClgIC0tIGRheSBvZiB0aGUgd2VlawoKQnkgZGVmYXVsdCwgYHdkYXkoKWAgcmV0dXJucyBhbiBpbnRlZ2VyOgoKYGBge3J9CndkYXkodG9kYXkoKSkKYGBgCgpCdXQgaXQgY2FuIGFsc28gcmV0dXJuIGEgbGFiZWw6CgpgYGB7cn0Kd2RheSh0b2RheSgpLCBsYWJlbCA9IFRSVUUpCmBgYAoKYGBge3J9CndkYXkodG9kYXkoKSwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpCmBgYAoKV2Vla2RheSBuYW1lcyBhbmQgYWJicmV2aWF0aW9ucyBhcmUgb2J2aW91c2x5IGxvY2FsZS1zcGVjaWZpYywgYW5kIHlvdQpjYW4gc3BlY2lmeSBhbiBhbHRlcm5hdGl2ZSB0byB0aGUgZGVmYXVsdCBjdXJyZW50IGxvY2FsZToKCmBgYHtyfQp3ZGF5KHRvZGF5KCksIGxhYmVsID0gVFJVRSwgYWJiciA9IEZBTFNFLCBsb2NhbGUgPSAiZGVfREUuVVRGLTgiKQpgYGAKCmBgYHtyfQp3ZGF5KHRvZGF5KCksIGxhYmVsID0gVFJVRSwgbG9jYWxlID0gImRlX0RFLlVURi04IikKYGBgCgpFdmVuIHRoZSBpbnRlZ2VyIHZhbHVlIGNhbiBiZSB0cmlja3k6CgoqIEluIHRoZSBVUywgQ2FuYWRhLCBKYXBhbiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrIGlzIFN1bmRheS4KCiogSW4gR2VybWFueSwgRnJhbmNlLCBhbmQgdGhlIElTTzg2MDEgc3RhbmRhcmQgdGhlIGZpcnN0IGRheSBvZiB0aGUKICB3ZWVrIGlzIE1vbmRheS4KCmB3ZGF5KClgIGNhbiBiZSBhc2tlZCB0byB1c2UgYSBkaWZmZXJlbnQgZmlyc3QgZGF5LCBhbmQgYSBnbG9iYWwgZGVmYXVsdApjYW4gYmUgc2V0LgoKVXNpbmcgYHdkYXkoKWAgYW5kIHRoZSBgZGF0ZWAgdmFyaWFibGUgd2UgY2FuIGxvb2sgYXQgdGhlIGRpc3RyaWJ1dGlvbgpvZiB0aGUgbnVtYmVyIG9mIGZsaWdodHMgYnkgZGF5IG9mIHRoZSB3ZWVrOgoKYGBge3IgZmxpZ2h0cy13ZGF5LCBldmFsID0gRkFMU0V9CmdncGxvdChmbCwgYWVzKHggPSB3ZGF5KGRhdGUsIGxhYmVsID0gVFJVRSkpKSArCiAgICBnZW9tX2JhcihmaWxsID0gImRlZXBza3libHVlMyIpCmBgYAoKYGBge3IgZmxpZ2h0cy13ZGF5LCBlY2hvID0gRkFMU0V9CmBgYAoKVGhlcmUgd2VyZSBzdWJzdGFudGlhbGx5IGZld2VyIGZsaWdodHMgb24gU2F0dXJkYXlzIGJ1dCBvbmx5IHNsaWdodGx5CmZld2VyIGZsaWdodHMgb24gU3VuZGF5cy4KCgojIyBSb3VuZGluZwoKYGZsb29yX2RhdGUoKWAsIGByb3VuZF9kYXRlKClgLCBhbmQgYGNlaWxpbmdfZGF0ZSgpYCBjYW4gYmUgdXNlZCB0bwpyb3VuZCB0byBhIHBhcnRpY3VsYXIgdW5pdDsgdGhlIG1vc3QgdXNlZnVsIGFyZSBgd2Vla2AgYW5kIGBxdWFydGVyYC4KCkZsaWdodHMgYnkgd2VlazoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGRwaSA9IDMwMCwgZmlnLmhlaWdodCA9IDR9CmdncGxvdChmbCwgYWVzKHggPSByb3VuZF9kYXRlKGRhdGUsICJ3ZWVrIikpKSArCiAgICBnZW9tX2JhcihmaWxsID0gImRlZXBza3libHVlMyIpCmBgYAoKVGhlIGZpcnN0IGFuZCBsYXN0IHdlZWtzIHdlcmUgaW5jb21wbGV0ZToKCmBgYHtyfQphcy5jaGFyYWN0ZXIod2RheSh5bWQoIjIwMTMtMDEtMDEiKSwKICAgICAgICAgICAgICAgICAgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpKQpgYGAKYGBge3J9CmFzLmNoYXJhY3Rlcih3ZGF5KHltZCgiMjAxMy0xMi0zMSIpLAogICAgICAgICAgICAgICAgICBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkpCmBgYAoKCiMjIFRpbWUgU3BhbnMKClN1YnRyYWN0aW5nIGRhdGVzIG9yIGRhdGUtdGltZXMgcHJvZHVjZXMgYGRpZmZ0aW1lYCBvYmplY3RzOgoKYGBge3J9Cm5vdygpIC0gYXNfZGF0ZXRpbWUodG9kYXkoKSkKYGBgCgpgYGB7cn0KdG9kYXkoKSAtIHltZCgiMjAyNi0wMS0wMSIpCmBgYAoKV29ya2luZyB3aXRoIGRpZmZlcmVudCB1bml0cyBjYW4gYmUgYXdrd2FyZDsgYGx1YnJpZGF0ZWAgcHJvdmlkZXMKX2R1cmF0aW9uc18sIHdoaWNoIGFsd2F5cyB3b3JrIGluIHNlY29uZHM6CgpgYGB7cn0KYXMuZHVyYXRpb24obm93KCkgLSBhc19kYXRldGltZSh0b2RheSgpKSkKYGBgCgpgYGB7cn0KYXMuZHVyYXRpb24odG9kYXkoKSAtIHltZCgiMjAyNi0wMS0wMSIpKQpgYGAKCkR1cmF0aW9ucyBjYW4gYmUgY3JlYXRlZCB3aXRoIGBkeWVhcnMoKWAsIGBkZGF5cygpYCwgYGR3ZWVrcygpYCwgZXRjLjoKCmBgYHtyfQpkeWVhcnMoMSkKYGBgCgpgYGB7cn0KZGRheXMoMSkKYGBgCgpEdXJhdGlvbnMgY2FuIGJlIGFkZGVkIHRvIGEgZGF0ZSBvciBkYXRlLXRpbWUgb2JqZWN0IGFuZCBjYW4gYmUKbXVsdGlwbGllZCBieSBhIG51bWJlcjoKCmBgYHtyfQp0b2RheSgpCmBgYAoKYGBge3J9CnRvZGF5KCkgKyBkZGF5cygyKQpgYGAKCmBgYHtyfQp0b2RheSgpICsgMiAqIGRkYXlzKDEpCmBgYAoKYGBge3J9CihuMSA8LSBub3coKSkKYGBgCgpgYGB7cn0KbjEgKyBkbWludXRlcygzKQpgYGAKCkR1YXRpb25zIHJlcHJlc2VudCBhbiBleGFjdCBudW1iZXIgb2Ygc2Vjb25kcywgd2hpY2ggY2FuIGxlYWQgdG8Kc3VycHJpc2VzIHdoZW4gRFNUIGlzIGludm9sdmVkLgoKSW4gMjAyNiB0aGUgc3dpdGNoIHRvIERTVCBoYXBwZW5lZCBpbiB0aGUgVVMgb24gTWFyY2ggODoKCmBgYHtyfQp5bWRfaG0oIjIwMjYtMDMtMDcgMjM6MDIiLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iKSArIGRkYXlzKDEpCmBgYAoKX1BlcmlvZHNfIGFyZSBhbiBhbHRlcm5hdGl2ZSB0aGF0IG1heSB3b3JrIG1vcmUgaW50dWl0aXZlbHkuCgpQZXJpb2RzIGFyZSBjb25zdHJ1Y3RlZCB3aXRoIGB5ZWFycygpYCwgYG1vbnRocygpYCwgYGRheXMoKWAsIGV0YzoKCmBgYHtyfQp5bWRfaG0oIjIwMjYtMDMtMDcgMjM6MDIiLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iKSArIGRheXMoMSkKYGBgCgoKIyMgVGltZSBab25lcwoKRGF0ZS10aW1lIG9iamVjdHMgc3BlY2lmeSBhIHBvaW50IGluIHRpbWUgcmVsYXRpdmUgdG8gc2Vjb25kIHplcm8sCm1pbnV0ZSB6ZXJvLCBob3VyIHplcm8sIG9uIEphbnVhcnkgMSwgMTk3MCBpbgpbQ29vcmRpbmF0ZWQgVW5pdmVyc2FsIFRpbWUgKFVUQyldKGh0dHBzOi8vd3d3LnRpbWVhbmRkYXRlLmNvbS90aW1lL2Fib3V0dXRjLmh0bWwpLgoKRGF0ZS10aW1lIG9iamVjdHMgY2FuIGhhdmUgYSB0aW1lIHpvbmUgYXNzb2NpYXRlZCB3aXRoIHRoZW0gdGhhdAphZmZlY3RzIGhvdyB0aGV5IGFyZSBwcmludGVkLgoKYG5vdygpYCByZXR1cm5zIGEgZGF0ZS10aW1lIG9iamVjdCB3aXRoIHRoZSB0aW1lIHpvbmUgc2V0IGFzIHRoZQpsb2NhbCB0aW1lIHpvbmUgb2YgdGhlIGNvbXB1dGVyLgoKYGBge3J9Cm5vdygpCmBgYAoKVGltZSB6b25lcyBhcmUgY29tcGxleCwgdGhleSBjYW4gY2hhbmdlIG9uIGEgcmVndWxhciBiYXNpcyAoRFNUKSBvciBhcwphIHJlc3VsdCBvZiBwb2xpdGljcy4KCldoZW4gYSBkYXRlLXRpbWUgb2JqZWN0IGlzIGNyZWF0ZWQgZnJvbSBjb21wb25lbnRzLCBieSBkZWZhdWx0IGl0IGlzCmdpdmVuIHRoZSBVVEMgdGltZSB6b25lLgoKVG8gY3JlYXRlIGEgcG9pbnQgaW4gdGltZSBiYXNlZCBvbiBsb2NhbCB0aW1lIGluZm9ybWF0aW9uLCBzdWNoIGFzIDEwCkFNIG9uIEFwcmlsIDE1LCAyMDI2LCBpbiBJb3dhIENpdHksIGEgdGltZSB6b25lIGZvciBpbnRlcnByZXRpbmcgdGhlCmxvY2FsIHRpbWUgbmVlZHMgdG8gYmUgc3BlY2lmaWVkLgoKVGhlIHNob3J0IG5vdGF0aW9ucyBsaWtlIENEVCBhcmUgbm90IGFkZXF1YXRlIGZvciB0aGlzOiBCb3RoIHRoZSBVUwogYW5kIEF1c3RyYWxpYSBoYXZlIEVTVCwgd2hpY2ggYXJlIHF1aXRlIGRpZmZlcmVudC4KClIgdXNlcyB0aGUKW19JbnRlcm5ldCBBc3NpZ25lZCBOdW1iZXJzIEF1dGhvcml0eV8gKElBTkEpXShodHRwczovL3d3dy5pYW5hLm9yZy90aW1lLXpvbmVzKQpuYW1pbmcgY29udmVudGlvbiBhbmQgZGF0YSBiYXNlLgoKVGhlIGxvY2FsIHRpbWUgem9uZSBpczoKCmBgYHtyfQpTeXMudGltZXpvbmUoKQpgYGAKClRoZSB0aW1lIHBvaW50IDEwOjAwOjAwIEFNIG9uIEFwcmlsIDE1LCAyMDI2IGluIElvd2EgQ2l0eSBjYW4gYmUKc3BlY2lmaWVkIGFzCgpgYGB7cn0KKHRtIDwtIG1ha2VfZGF0ZXRpbWUoMjAyNiwgNCwgMTUsIDEwLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iKSkKYGBgCgpUaW1lIHpvbmVzIG9mIGRhdGUtdGltZSBvYmplY3RzIGNhbiBiZSBjaGFuZ2VkIGluIHR3byB3YXlzOgoKKiBgd2l0aF90emAga2VlcHMgdGhlIGluc3RhbnQgaW4gdGltZSBhbmQgY2hhbmdlcyB0aGUgdGltZSB6b25lIHVzZWQKICBmb3IgZGlzcGxheS4KCiogYGZvcmNlX3R6YCBjaGFuZ2VzIHRoZSBpbnN0YW50IGluIHRpbWU7IHVzZSB0aGlzIGlmIHRoZSB0aW1lIHpvbmUgaXMKICBpbmNvcnJlY3RseSBzcGVjaWZpZWQgYnV0IHRoZSBjbG9jayB0aW1lIGlzIGNvcnJlY3QuCgpUaGUgYXZhaWxhYmxlIHRpbWUgem9uZSBzcGVjaWZpY2F0aW9ucyBhcmUgY29udGFpbmVkIGluIGBPbHNvbk5hbWVzYDoKCmBgYHtyfQpoZWFkKE9sc29uTmFtZXMoKSkKYGBgCgpUaGUgaW5zdGFudCBgdG1gIGluIHNvbWUgb3RoZXIgdGltZSB6b25lczoKCmBgYHtyfQp3aXRoX3R6KHRtLCB0eiA9ICJVVEMiKQpgYGAKCmBgYHtyfQp3aXRoX3R6KHRtLCB0eiA9ICJBbWVyaWNhL05ld19Zb3JrIikKYGBgCgpgYGB7cn0Kd2l0aF90eih0bSwgdHogPSAiQXNpYS9TaGFuZ2hhaSIpCmBgYAoKYGBge3J9CndpdGhfdHoodG0sIHR6ID0gIlBhY2lmaWMvQXVja2xhbmQiKQpgYGAKCmBgYHtyfQp3aXRoX3R6KHRtLCB0eiA9ICJBc2lhL0tvbGthdGEiKQpgYGAKCmBgYHtyfQp3aXRoX3R6KHRtLCB0eiA9ICJBbWVyaWNhL1N0X0pvaG5zIikKYGBgCgpgYGB7cn0Kd2l0aF90eih0bSwgdHogPSAiQXNpYS9LYXRobWFuZHUiKQpgYGAKClNvbWUgbW9yZSBleGFtcGxlczoKCmBgYHtyLCBldmFsID0gRkFMU0V9CiMjIEFsbCBvZmZzZXRzIHRoYXQgYXJlIG5vdCBhIGZ1bGwgaG91cjoKZ2V0X29mZnNldCA8LSBmdW5jdGlvbih6KQogICAgYWJzKG1pbnV0ZSh3aXRoX3R6KHRtLCB0eiA9IHopKSAtIG1pbnV0ZSh0bSkpCm9mZnNldHMgPC0gZGF0YS5mcmFtZSh6b25lID0gT2xzb25OYW1lcygpKSB8PgogICAgbXV0YXRlKG9mZnNldCA9IHNhcHBseSh6b25lLCBnZXRfb2Zmc2V0KSkgfD4KICAgIGFycmFuZ2Uob2Zmc2V0KQpmaWx0ZXIob2Zmc2V0cywgb2Zmc2V0ICE9IDApCgojIyBPZmZzZXRzIGZvciBBdXN0cmFsaWE6CmZpbHRlcihvZmZzZXRzLCBncmVwbCgiQXVzdHJhbGlhIiwgem9uZSkpCmBgYAoKSWYgd2UgY3JlYXRlIHRoZSBgdGhgIHZhcmlhYmxlIGZvciB0aGUgZmxpZ2h0cyBkYXRhIGFzCgpgYGB7cn0KZmwgPC0gbXV0YXRlKGZsaWdodHMsIHRoID0gbWFrZV9kYXRldGltZSh5ZWFyLCBtb250aCwgZGF5LCBob3VyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR6ID0gIkFtZXJpY2EvTmV3X1lvcmsiKSkKYGBgCgp0aGVuIHRoZSByZXN1bHQgbWF0Y2hlcyB0aGUgYGRhdGVfdGltZWAgdmFyaWFibGU6CgpgYGB7cn0KaWRlbnRpY2FsKGZsJHRoLCBmbCR0aW1lX2hvdXIpCmBgYAoKVGhlIGB0aW1lX2hvdXJgIHZhcmlhYmxlIGluIHRoZSBgd2VhdGhlcmAgdGFibGUgcmVmbGVjdHMgYWN0dWFsIHBvaW50cwppbiB0aW1lIGFuZCwgdG9nZXRoZXIgd2l0aCBgb3JpZ2luYCwgY2FuIHNlcnZlIGFzIGEgcHJpbWFyeSBrZXk6CgpgYGB7cn0KZmlsdGVyKGNvdW50KHdlYXRoZXIsIG9yaWdpbiwgdGltZV9ob3VyKSwgbiA+IDEpCmBgYAoKVGhlIGBtb250aGAsIGBkYXlgLCBgaG91cmAgdmFyaWFibGVzIGFyZSBjb25mdXNlZCBieSB0aGUgdGltZQpjaGFuZ2UuCgpJbiBOb3ZlbWJlciB0aGVyZSBpcyBhIHJlcGVhdDoKCmBgYHtyfQpjb3VudCh3ZWF0aGVyLCBvcmlnaW4sIG1vbnRoLCBkYXksIGhvdXIpIHw+CiAgICBmaWx0ZXIobiA+IDEpCmBgYAoKYW5kIHRoZXJlIGlzIGEgbWlzc2luZyBob3VyIGluIE1hcmNoOgoKYGBge3J9CnNlbGVjdCh3ZWF0aGVyLCBvcmlnaW4sIG1vbnRoLCBkYXksIGhvdXIpIHw+CiAgICBmaWx0ZXIob3JpZ2luID09ICJFV1IiLCBtb250aCA9PSAzLAogICAgICAgICAgIGRheSA9PSAxMCwgaG91ciA8PSAzKQpgYGAKCgojIyBUaGluZ3MgdG8gTG9vayBPdXQgRm9yCgpGb3IgZGF0ZXM6CgoqIExhbmd1YWdlIHVzZWQgZm9yIG1vbnRocyBhbmQgd2Vla2RheXMsIGFuZCB0aGVpciBhYmJyZXZpYXRpb25zLgoKKiBBbWJpZ3VvdXMgbnVtZXJpY2FsIGNvbnZlbnRpb25zIGxpa2UgNC8xMS8yMDI2OiBpcyB0aGlzIEFwcmlsIDExIG9yCiAgTm92ZW1iZXIgND8KCiogRGF5IDIgb2YgdGhlIHdlZWs6IGlzIHRoaXMgTW9uZGF5IG9yIFR1ZXNkYXk/CgoqIEZvciBoaXN0b3JpY2FsIGRhdGEsIHdoYXQgY2FsZW5kYXIgaXMgYmVpbmcgdXNlZD8gKFRoZSBfT2N0b2JlcgogIFJldm9sdXRpb25fIGhhcHBlbmVkIG9uIE5vdmVtYmVyIDYvNywgMTkxNyBieSB0aGUgY3VycmVudCBHcmVnb3JpYW4KICBjYWxlbmRhcjsgT2N0b2JlciAyNC8yNSBieSB0aGUgSnVsaWFuIGNhbGVuZGFyIFJ1c3NpYSB3YXMgc3RpbGwKICB1c2luZy4pCgpGb3IgZGF0ZS10aW1lcwoKKiBBbGwgb2YgdGhlIGFib3ZlLgoKKiBEYXlsaWdodCBzYXZpbmcgdGltZS4KCiogVGltZSB6b25lcy4KCjwhLS0KTG9jYWxlIHN0dWZmIG1heSBmYWlsIG9uIHNvbWUgc3lzdGVtcyAob24gVWJ1bnR1IG1heSBuZWVkIHRvIHVzZQpsb2NhbGUtZ2VuCi0tPgo8IS0tCmxpYnJhcnkobHVicmlkYXRlKQpmbGlnaHRzIDwtIG11dGF0ZShmbGlnaHRzLCB0aCA9IG1ha2VfZGF0ZXRpbWUoeWVhciwgbW9udGgsIGRheSwgaG91ciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR6ID0gIkFtZXJpY2EvTmV3X1lvcmsiKSkKd2VhdGhlciA8LSBtdXRhdGUod2VhdGhlciwgdGggPSBtYWtlX2RhdGV0aW1lKHllYXIsIG1vbnRoLCBkYXksIGhvdXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eiA9ICJVVEMiKSkKCmZsMCA8LSBzZWxlY3QoZmlsdGVyKGZsaWdodHMsIG9yaWdpbiA9PSAiTEdBIiksCiAgICAgICAgICAgICAgZGVwX3RpbWUsIHRpbWVfaG91ciwgdGgpCncwIDwtIHNlbGVjdChmaWx0ZXIod2VhdGhlciwgb3JpZ2luID09ICJMR0EiKVstKDEgOiA5KSxdLAogICAgICAgICAgICAgdGltZV9ob3VyLCB0aCwgdGVtcCkKCmZsMSA8LSBsZWZ0X2pvaW4oZmwwLCBzZWxlY3QodzAsIC10aCksICJ0aW1lX2hvdXIiKQpmbDIgPC0gbGVmdF9qb2luKGZsMCwgc2VsZWN0KHcwLCAtdGltZV9ob3VyKSwgInRoIikKLS0+CgoKIyMgUmVhZGluZwoKQ2hhcHRlciBbX0RhdGVzIGFuZCBUaW1lc19dKGh0dHBzOi8vcjRkcy5oYWRsZXkubnovZGF0ZXRpbWVzLmh0bWwpCmluIFtfUiBmb3IgRGF0YSBTY2llbmNlX10oaHR0cHM6Ly9yNGRzLmhhZGxleS5uei8pLgoKCiMjIEV4ZXJjaXNlcwoKMS4gVXNpbmcgdGhlIE5ZQyBmbGlnaHRzIGRhdGEsIGhvdyBtYW55IGZsaWdodHMgd2VyZSB0aGVyZSBvbgogICBTYXR1cmRheXMgZnJvbSBOZXdhcmsgKEVXUikgdG8gQ2ljYWdvIE8nSGFyZSAoT1JEKSBpbiAyMDEzPwogICAKICAgIGEuIDQxMwogICAgYi4gNTIyCiAgICBjLiA2MDEKICAgIGQuIDczMwogICAKCjIuIFdoYXQgZGF5IG9mIHRoZSB3ZWVrIHdpbGwgSnVseSA0LCAyMDMwLCBmYWxsIG9uPwoKICAgIGEuIE1vbmRheQogICAgYi4gV2VkbmVzZGF5CiAgICBkLiBUaHVyc2RheQogICAgYy4gU2F0dXJkYXkK