Introduction
Working with date and time objects is essential for time-series analysis and when working with temporal data. Breaking apart dates into day, month, or year components, or grouping by a date component are essential data shaping tasks. R, like many other languages, provides robust methods for handling dates and times, both through its base functionality and through specialized packages like lubridate. In this lesson, we will explore how to extract, parse, and manipulate date and time values in R using various approaches. Additionally, we will discuss important standards such as POSIX and ISO 8601 that underpin the representation of temporal data.
Date and Time Objects
In R, the Date
class is used to store dates without times. These objects are represented as the number of days since January 1, 1970 (the Unix epoch). The as.Date()
function is the primary tool for converting character data into Date
objects. Note the format of the input date is generally “YYYY-MM-DD” but the as.Date()
function also recognizes other formats as illustrated below.
# Converting character to Date
date1 <- as.Date("2025-01-23")
print(date1)
## [1] "2025-01-23"
## [1] "Date"
date2 <- as.Date("2025/01/23")
print(date2)
## [1] "2025-01-23"
Objects of class Date
can be used in calculations. The function makes automatic adjustments for leap years.
# Adding or subtracting days
future_date <- date1 + 10
print(future_date)
## [1] "2025-02-02"
Current Date and Time
To get the current time, you can use the Sys.time()
function. This function returns a POSIXct object that contains both the date and time, but you can extract only the time component if desired. The current date and time can be obtained using the mechanisms illustrated below:
# Get the current time
current_time <- Sys.time()
print(current_time) # Example output: "2025-01-23 15:45:12 UTC"
## [1] "2025-01-24 07:22:40 EST"
# Extract only the time component using strftime
time_only <- format(current_time, "%H:%M:%S")
print(time_only) # Example output: "15:45:12"
## [1] "07:22:40"
The format()
function can be used to extract various date or time elements. Of course, other text processing functions can be used as well.
POSIXt Classes: POSIXct and POSIXlt
For date-time values, R provides the POSIXt
class, which has two implementations: POSIXct
and POSIXlt
. These classes are designed to handle both dates and times.
POSIXct
: Represents date-time as the number of seconds since the Unix epoch. It is useful for computations.
POSIXlt
: Stores date-time as a list with separate components (e.g., year, month, day, hour).
# Creating a POSIXct object
datetime1 <- as.POSIXct("2025-01-23 14:30:00")
print(datetime1)
class(datetime1)
# Extracting components from a POSIXlt object
datetime2 <- as.POSIXlt(datetime1)
print(datetime2$hour) # Extracting hour
Parsing Date Objects
Extracting various elements of the date and time from a Date
object or date formatted text string can be done using various text processing functions such as substr()
or using the format()
function. Additional convenience functions exist within the lubridate package explained in detail in a subsequent section. For now, we will present various examples of extracting different elements.
Note that the Sys.time()
function returns a POSIXct formatted object and not an ISO 8601 formatted string. Both format are explained in more detailed below. The format of a POSIXct object is: “YYYY-MM-DD hh:mm:ss UTC”, e.g., “2025-01-23 15:45:12 UTC”. Since we use string processing functions to extract the elements, they will be of type “character”; any calculation with them will require a conversion to an integer using the as.integer()
function.
# Get the current time
now <- Sys.time()
# Extract the year
year <- substr(now, 1, 4)
print(year)
## [1] "2025"
# Extract the month
month <- substr(now, 6, 7)
print(month)
## [1] "01"
# Extract the hour and minutes
hr_min <- format(now, "%H:%M")
print(hr_min)
## [1] "07:22"
Of course, we could have used the substr()
function for the hr_min extraction or even a regular expression. There isn’t a single correct approach; it is programming preference and ease of comprehensibility.
An alternative for parsing formatted date and time string is the strptime()
function. Similar to the format()
function shown below, the formats must adhere to specific codes, such as %Y
for the year, %m
for the month, and %d
for the day.
# Parsing a custom date-time string
datetime_str <- "23-01-2025 14:30:00"
parsed_datetime <- strptime(datetime_str, format = "%d-%m-%Y %H:%M:%S")
print(parsed_datetime)
## [1] "2025-01-23 14:30:00 EST"
format
Function
The format()
function in R is a often used to format and extract components from date and time objects. It allows you to convert Date
or POSIXt
objects into character strings with customized formats, suitable for extracting specific date or time elements.
The basic syntax for format is show below:
format(x, format = "", tz = "", usetz = FALSE)
Here is a detailed explanation of each parameter:
x
:
- The input date or time object, such as a
Date
, POSIXct
, or POSIXlt
object. This is the value you want to format.
format
:
- A character string specifying the desired output format. This string uses specific placeholders (format codes) to represent components of the date and time.
- Common format codes include:
%Y
: Full year (e.g., “2025”).
%y
: Last two digits of the year (e.g., “25”).
%m
: Month as a two-digit number (e.g., “01”).
%B
: Full month name (e.g., “January”).
%b
: Abbreviated month name (e.g., “Jan”).
%d
: Day of the month as a two-digit number (e.g., “23”).
%H
: Hour in 24-hour format (e.g., “15”).
%I
: Hour in 12-hour format (e.g., “03”).
%M
: Minute (e.g., “45”).
%S
: Second (e.g., “12”).
%p
: AM/PM indicator.
%A
: Full weekday name (e.g., “Thursday”).
%a
: Abbreviated weekday name (e.g., “Thu”).
%j
: Day of the year as a number (e.g., “023”).
%W
: Week number of the year (starting with Monday as the first day of the week).
%w
: Weekday number (0 = Sunday, 1 = Monday, etc.).
%z
: Timezone offset (e.g., “-0500”).
%Z
: Timezone abbreviation (e.g., “UTC”).
tz
:
- A character string specifying the desired time zone (e.g.,
"UTC"
, "America/New_York"
). If not provided, the system’s default time zone is used.
usetz
:
- A logical value (
TRUE
or FALSE
) that specifies whether to include the time zone abbreviation in the formatted output. This is relevant for POSIXt
objects.
Let’s take a look at some examples. You can format a Date
object to extract or display specific components.
# Creating a Date object
date_obj <- as.Date("2025-01-23")
# Extracting the year
year <- format(date_obj, "%Y")
print(year) # Output: "2025"
## [1] "2025"
# Extracting the month as a name
month_name <- format(date_obj, "%B")
print(month_name) # Output: "January"
## [1] "January"
# Extracting the day of the week
weekday <- format(date_obj, "%A")
print(weekday) # Output: "Thursday"
## [1] "Thursday"
The format() function also works with POSIXct
objects in addition to Date
objects.
# Creating a POSIXct object
datetime_obj <- as.POSIXct("2025-01-23 15:45:12", tz = "UTC")
# Extracting the hour
hour <- format(datetime_obj, "%H")
print(hour) # Output: "15"
## [1] "15"
# Extracting the minute
minute <- format(datetime_obj, "%M")
print(minute) # Output: "45"
## [1] "45"
# Extracting the timezone
timezone <- format(datetime_obj, "%Z")
print(timezone) # Output: "UTC"
## [1] "UTC"
Here is a more elaborate example in which we combine different components to create custom date-time strings.
# Custom formatted string
custom_format <- format(datetime_obj, "%d-%b-%Y %I:%M %p (%Z)")
print(custom_format) # Output: "23-Jan-2025 03:45 PM (UTC)"
## [1] "23-Jan-2025 03:45 PM (UTC)"
The tz
parameter allows you to format the date-time in a specific time zone allowing for conversion to a common time zone or to localize times.
# Formatting with a specific time zone
datetime_obj_tz <- format(datetime_obj, "%Y-%m-%d %H:%M:%S %Z", tz = "America/New_York")
print(datetime_obj_tz) # Output: "2025-01-23 10:45:12 EST"
## [1] "2025-01-23 10:45:12 EST"
The usetz
parameter can be used to control whether the time zone is displayed in the output.
# Including the time zone
formatted_with_tz <- format(datetime_obj, "%Y-%m-%d %H:%M:%S", usetz = TRUE)
print(formatted_with_tz) # Output: "2025-01-23 15:45:12 UTC"
## [1] "2025-01-23 15:45:12 UTC"
# Excluding the time zone
formatted_without_tz <- format(datetime_obj, "%Y-%m-%d %H:%M:%S", usetz = FALSE)
print(formatted_without_tz) # Output: "2025-01-23 15:45:12"
## [1] "2025-01-23 15:45:12"
The format()
function is a commonly used date parsing function because you can:
- extract specific date or time elements (e.g., year, month, day, hour).
- create custom date-time strings for display or reporting purposes.
- convert date-time objects into character strings for labeling or exporting data.
Parsing Date Strings
Data files often have date and time stamps in non-standard format which require test processing functions to extract the various components. In such situations, the format()
or strptime()
functions is not appropriate as the date strings do not correspond to a Date
or POSIXct
format.
d <- "Dec 24, 2024"
month <- substr(d, 1, 3)
day <- substr(d, 5, 6)
months <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
month_num <- which(months == month)
month_day <- paste0(month_num, "/", day)
print(month_day)
## [1] "12/24"
Of course, the above code gets a bit more challenging if the encoding allows for “Dec 3, 2024” and “Apr 12, 2024” as the day is either one or two digits. In this situation looking for the comma might be better or applying a regular expression. This can be fun…
The lubridate Package
While Base R offers a plethora of functions, the lubridate package simplifies many common date-time operations with simpler-to-use functions. This package is particularly useful for parsing, extracting, and manipulating date-time values.
The lubridate
package provides intuitive functions like ymd()
, mdy()
, and dmy()
for parsing dates in different formats.
library(lubridate)
# Parsing with lubridate
date_parsed <- ymd("2025-01-23")
print(date_parsed)
## [1] "2025-01-23"
datetime_parsed <- ymd_hms("2025-01-23 14:30:00")
print(datetime_parsed)
## [1] "2025-01-23 14:30:00 UTC"
lubridate makes it easier to extract specific components of date-time objects using functions like year()
, month()
, and day()
. Some examples are shown below.
# Extracting components
year_val <- year(datetime_parsed)
month_val <- month(datetime_parsed)
day_val <- day(datetime_parsed)
print(paste("Year:", year_val, "Month:", month_val, "Day:", day_val))
## [1] "Year: 2025 Month: 1 Day: 23"
Additionally, lubridate simplifies date-time arithmetic. For example, you correctly can add months, days, or years to a date.
# Adding duration
new_date <- date_parsed + months(2)
print(new_date)
## [1] "2025-03-23"
# Computing differences
date_diff <- as.duration(interval(date_parsed, new_date))
print(date_diff)
## [1] "5097600s (~8.43 weeks)"
Standards: POSIX and ISO 8601
POSIX
POSIX (Portable Operating System Interface) defines how date-time values are represented and manipulated in Unix-like systems. In R, POSIXct and POSIXlt adhere to this standard.
ISO 8601
ISO 8601 is an international standard for representing dates and times in a consistent, unambiguous format. It uses formats such as YYYY-MM-DD for dates and YYYY-MM-DDTHH:MM:SS for date-time values. The full datetime stamp structure is shown in the diagram below. Notice the use of ‘-’ as the separator for the date elements and ‘:’ as the separator for the time elements. A dot (.) separates the milliseconds. The hours are in 24-hour format – there is no accommodation for an ‘am’ or ‘pm’ indicator.

The functions of lubridate automatically recognize and handle ISO 8601 formatted date and time strings.
Summary
In this lesson, we explored the foundational tools in Base R for working with date and time objects, including Date
, POSIXct
, and POSIXlt
. We also introduced the lubridate package, which simplifies parsing, extraction, and computation. Along the way, we discussed important standards like POSIX and ISO 8601, which ensure consistency in date-time representations, particularly across programming languages and databases.
References
No references.
LS0tCnRpdGxlOiAiV29ya2luZyB3aXRoIERhdGUgYW5kIFRpbWUgVmFsdWVzIGluIFIiCnBhcmFtczoKICBjYXRlZ29yeTogNgogIG51bWJlcjogMTEzCiAgdGltZTogOTAKICBsZXZlbDogYmVnaW5uZXIKICB0YWdzOiAicixkYXRlLHRpbWUsbHVicmlkYXRlLHRpbWVzdGFtcHMiCiAgZGVzY3JpcHRpb246ICJFeHBsYWlucyBkYXRlIGFuZCB0aW1lIHZhbHVlIGFuZCB0aGUgdmFyaW91cwogICAgICAgICAgICAgICAgUiBvYmplY3RzIGZvciBzdG9yaW5nIHRoZW0gc3VjaCwgaW5jbHVkaW5nCiAgICAgICAgICAgICAgICBEYXRlLiBJbnRyb2R1Y2VzIHRoZSBsdWJyaWRhdGUgcGFja2FnZS4iCmRhdGU6ICI8c21hbGw+YHIgU3lzLkRhdGUoKWA8L3NtYWxsPiIKYXV0aG9yOiAiPHNtYWxsPk1hcnRpbiBTY2hlZGxiYXVlcjwvc21hbGw+IgplbWFpbDogIm0uc2NoZWRsYmF1ZXJAbmV1LmVkdSIKYWZmaWxpdGF0aW9uOiAiTm9ydGhlYXN0ZXJuIFVuaXZlcnNpdHkiCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBzcGFjZWxhYgogICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCi0tLQp0aXRsZTogIjxzbWFsbD5gciBwYXJhbXMkY2F0ZWdvcnlgLmByIHBhcmFtcyRudW1iZXJgPC9zbWFsbD48YnIvPjxzcGFuIHN0eWxlPSdjb2xvcjogIzJFNDA1MzsgZm9udC1zaXplOiAwLjllbSc+YHIgcm1hcmtkb3duOjptZXRhZGF0YSR0aXRsZWA8L3NwYW4+IgotLS0KCmBgYHtyIGVjaG89Rn0KIyBQYWNrYWdlIG5hbWVzCnBhY2thZ2VzIDwtIGMoImhlcmUiLCAibHVicmlkYXRlIikKCiMgSW5zdGFsbCBwYWNrYWdlcyBub3QgeWV0IGluc3RhbGxlZAppbnN0YWxsZWRfcGFja2FnZXMgPC0gcGFja2FnZXMgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkKaWYgKGFueShpbnN0YWxsZWRfcGFja2FnZXMgPT0gRkFMU0UpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlc1shaW5zdGFsbGVkX3BhY2thZ2VzXSwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikKfQoKIyBQYWNrYWdlcyBsb2FkaW5nCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyhpbnZpc2libGUobGFwcGx5KHBhY2thZ2VzLCBsaWJyYXJ5LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSkKYGBgCgpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9faW5zZXJ0MkRCLlInKSksIGluY2x1ZGUgPSBGQUxTRX0KYGBgCgojIyBJbnRyb2R1Y3Rpb24KCldvcmtpbmcgd2l0aCBkYXRlIGFuZCB0aW1lIG9iamVjdHMgaXMgZXNzZW50aWFsIGZvciB0aW1lLXNlcmllcyBhbmFseXNpcyBhbmQgd2hlbiB3b3JraW5nIHdpdGggdGVtcG9yYWwgZGF0YS4gQnJlYWtpbmcgYXBhcnQgZGF0ZXMgaW50byBkYXksIG1vbnRoLCBvciB5ZWFyIGNvbXBvbmVudHMsIG9yIGdyb3VwaW5nIGJ5IGEgZGF0ZSBjb21wb25lbnQgYXJlIGVzc2VudGlhbCBkYXRhIHNoYXBpbmcgdGFza3MuIFIsIGxpa2UgbWFueSBvdGhlciBsYW5ndWFnZXMsIHByb3ZpZGVzIHJvYnVzdCBtZXRob2RzIGZvciBoYW5kbGluZyBkYXRlcyBhbmQgdGltZXMsIGJvdGggdGhyb3VnaCBpdHMgYmFzZSBmdW5jdGlvbmFsaXR5IGFuZCB0aHJvdWdoIHNwZWNpYWxpemVkIHBhY2thZ2VzIGxpa2UgKipsdWJyaWRhdGUqKi4gSW4gdGhpcyBsZXNzb24sIHdlIHdpbGwgZXhwbG9yZSBob3cgdG8gZXh0cmFjdCwgcGFyc2UsIGFuZCBtYW5pcHVsYXRlIGRhdGUgYW5kIHRpbWUgdmFsdWVzIGluIFIgdXNpbmcgdmFyaW91cyBhcHByb2FjaGVzLiBBZGRpdGlvbmFsbHksIHdlIHdpbGwgZGlzY3VzcyBpbXBvcnRhbnQgc3RhbmRhcmRzIHN1Y2ggYXMgUE9TSVggYW5kIElTTyA4NjAxIHRoYXQgdW5kZXJwaW4gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRlbXBvcmFsIGRhdGEuCgojIyBEYXRlIGFuZCBUaW1lIE9iamVjdHMKCkluIFIsIHRoZSBgRGF0ZWAgY2xhc3MgaXMgdXNlZCB0byBzdG9yZSBkYXRlcyB3aXRob3V0IHRpbWVzLiBUaGVzZSBvYmplY3RzIGFyZSByZXByZXNlbnRlZCBhcyB0aGUgbnVtYmVyIG9mIGRheXMgc2luY2UgSmFudWFyeSAxLCAxOTcwICh0aGUgVW5peCBlcG9jaCkuIFRoZSBgYXMuRGF0ZSgpYCBmdW5jdGlvbiBpcyB0aGUgcHJpbWFyeSB0b29sIGZvciBjb252ZXJ0aW5nIGNoYXJhY3RlciBkYXRhIGludG8gYERhdGVgIG9iamVjdHMuIE5vdGUgdGhlIGZvcm1hdCBvZiB0aGUgaW5wdXQgZGF0ZSBpcyBnZW5lcmFsbHkgIllZWVktTU0tREQiIGJ1dCB0aGUgYGFzLkRhdGUoKWAgZnVuY3Rpb24gYWxzbyByZWNvZ25pemVzIG90aGVyIGZvcm1hdHMgYXMgaWxsdXN0cmF0ZWQgYmVsb3cuCgpgYGB7cn0KIyBDb252ZXJ0aW5nIGNoYXJhY3RlciB0byBEYXRlCmRhdGUxIDwtIGFzLkRhdGUoIjIwMjUtMDEtMjMiKQpwcmludChkYXRlMSkKY2xhc3MoZGF0ZTEpCgpkYXRlMiA8LSBhcy5EYXRlKCIyMDI1LzAxLzIzIikKcHJpbnQoZGF0ZTIpCmBgYAoKT2JqZWN0cyBvZiBjbGFzcyBgRGF0ZWAgY2FuIGJlIHVzZWQgaW4gY2FsY3VsYXRpb25zLiBUaGUgZnVuY3Rpb24gbWFrZXMgYXV0b21hdGljIGFkanVzdG1lbnRzIGZvciBsZWFwIHllYXJzLgoKYGBge3J9CiMgQWRkaW5nIG9yIHN1YnRyYWN0aW5nIGRheXMKZnV0dXJlX2RhdGUgPC0gZGF0ZTEgKyAxMApwcmludChmdXR1cmVfZGF0ZSkKYGBgCgojIyBDdXJyZW50IERhdGUgYW5kIFRpbWUKClRvIGdldCB0aGUgY3VycmVudCB0aW1lLCB5b3UgY2FuIHVzZSB0aGUgYFN5cy50aW1lKClgIGZ1bmN0aW9uLiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgYSBQT1NJWGN0IG9iamVjdCB0aGF0IGNvbnRhaW5zIGJvdGggdGhlIGRhdGUgYW5kIHRpbWUsIGJ1dCB5b3UgY2FuIGV4dHJhY3Qgb25seSB0aGUgdGltZSBjb21wb25lbnQgaWYgZGVzaXJlZC4gVGhlIGN1cnJlbnQgZGF0ZSBhbmQgdGltZSBjYW4gYmUgb2J0YWluZWQgdXNpbmcgdGhlIG1lY2hhbmlzbXMgaWxsdXN0cmF0ZWQgYmVsb3c6CgpgYGB7cn0KIyBHZXQgdGhlIGN1cnJlbnQgdGltZQpjdXJyZW50X3RpbWUgPC0gU3lzLnRpbWUoKQpwcmludChjdXJyZW50X3RpbWUpICAjIEV4YW1wbGUgb3V0cHV0OiAiMjAyNS0wMS0yMyAxNTo0NToxMiBVVEMiCgojIEV4dHJhY3Qgb25seSB0aGUgdGltZSBjb21wb25lbnQgdXNpbmcgc3RyZnRpbWUKdGltZV9vbmx5IDwtIGZvcm1hdChjdXJyZW50X3RpbWUsICIlSDolTTolUyIpCnByaW50KHRpbWVfb25seSkgICMgRXhhbXBsZSBvdXRwdXQ6ICIxNTo0NToxMiIKYGBgCgpUaGUgYGZvcm1hdCgpYCBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBleHRyYWN0IHZhcmlvdXMgZGF0ZSBvciB0aW1lIGVsZW1lbnRzLiBPZiBjb3Vyc2UsIG90aGVyIHRleHQgcHJvY2Vzc2luZyBmdW5jdGlvbnMgY2FuIGJlIHVzZWQgYXMgd2VsbC4KCiMjIyBQT1NJWHQgQ2xhc3NlczogUE9TSVhjdCBhbmQgUE9TSVhsdAoKRm9yIGRhdGUtdGltZSB2YWx1ZXMsIFIgcHJvdmlkZXMgdGhlIGBQT1NJWHRgIGNsYXNzLCB3aGljaCBoYXMgdHdvIGltcGxlbWVudGF0aW9uczogYFBPU0lYY3RgIGFuZCBgUE9TSVhsdGAuIFRoZXNlIGNsYXNzZXMgYXJlIGRlc2lnbmVkIHRvIGhhbmRsZSBib3RoIGRhdGVzIGFuZCB0aW1lcy4KCi0gICBgUE9TSVhjdGA6IFJlcHJlc2VudHMgZGF0ZS10aW1lIGFzIHRoZSBudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSB0aGUgVW5peCBlcG9jaC4gSXQgaXMgdXNlZnVsIGZvciBjb21wdXRhdGlvbnMuCi0gICBgUE9TSVhsdGA6IFN0b3JlcyBkYXRlLXRpbWUgYXMgYSBsaXN0IHdpdGggc2VwYXJhdGUgY29tcG9uZW50cyAoZS5nLiwgeWVhciwgbW9udGgsIGRheSwgaG91cikuCgpgYGAgcgojIENyZWF0aW5nIGEgUE9TSVhjdCBvYmplY3QKZGF0ZXRpbWUxIDwtIGFzLlBPU0lYY3QoIjIwMjUtMDEtMjMgMTQ6MzA6MDAiKQpwcmludChkYXRldGltZTEpCmNsYXNzKGRhdGV0aW1lMSkKCiMgRXh0cmFjdGluZyBjb21wb25lbnRzIGZyb20gYSBQT1NJWGx0IG9iamVjdApkYXRldGltZTIgPC0gYXMuUE9TSVhsdChkYXRldGltZTEpCnByaW50KGRhdGV0aW1lMiRob3VyKSAgIyBFeHRyYWN0aW5nIGhvdXIKYGBgCgojIyBQYXJzaW5nIERhdGUgT2JqZWN0cwoKRXh0cmFjdGluZyB2YXJpb3VzIGVsZW1lbnRzIG9mIHRoZSBkYXRlIGFuZCB0aW1lIGZyb20gYSBgRGF0ZWAgb2JqZWN0IG9yIGRhdGUgZm9ybWF0dGVkIHRleHQgc3RyaW5nIGNhbiBiZSBkb25lIHVzaW5nIHZhcmlvdXMgdGV4dCBwcm9jZXNzaW5nIGZ1bmN0aW9ucyBzdWNoIGFzIGBzdWJzdHIoKWAgb3IgdXNpbmcgdGhlIGBmb3JtYXQoKWAgZnVuY3Rpb24uIEFkZGl0aW9uYWwgY29udmVuaWVuY2UgZnVuY3Rpb25zIGV4aXN0IHdpdGhpbiB0aGUgKipsdWJyaWRhdGUqKiBwYWNrYWdlIGV4cGxhaW5lZCBpbiBkZXRhaWwgaW4gYSBzdWJzZXF1ZW50IHNlY3Rpb24uIEZvciBub3csIHdlIHdpbGwgcHJlc2VudCB2YXJpb3VzIGV4YW1wbGVzIG9mIGV4dHJhY3RpbmcgZGlmZmVyZW50IGVsZW1lbnRzLgoKTm90ZSB0aGF0IHRoZSBgU3lzLnRpbWUoKWAgZnVuY3Rpb24gcmV0dXJucyBhIFBPU0lYY3QgZm9ybWF0dGVkIG9iamVjdCBhbmQgbm90IGFuIElTTyA4NjAxIGZvcm1hdHRlZCBzdHJpbmcuIEJvdGggZm9ybWF0IGFyZSBleHBsYWluZWQgaW4gbW9yZSBkZXRhaWxlZCBiZWxvdy4gVGhlIGZvcm1hdCBvZiBhIFBPU0lYY3Qgb2JqZWN0IGlzOiAiWVlZWS1NTS1ERCBoaDptbTpzcyBVVEMiLCAqZS5nLiosICIyMDI1LTAxLTIzIDE1OjQ1OjEyIFVUQyIuIFNpbmNlIHdlIHVzZSBzdHJpbmcgcHJvY2Vzc2luZyBmdW5jdGlvbnMgdG8gZXh0cmFjdCB0aGUgZWxlbWVudHMsIHRoZXkgd2lsbCBiZSBvZiB0eXBlICJjaGFyYWN0ZXIiOyBhbnkgY2FsY3VsYXRpb24gd2l0aCB0aGVtIHdpbGwgcmVxdWlyZSBhIGNvbnZlcnNpb24gdG8gYW4gaW50ZWdlciB1c2luZyB0aGUgYGFzLmludGVnZXIoKWAgZnVuY3Rpb24uCgpgYGB7cn0KIyBHZXQgdGhlIGN1cnJlbnQgdGltZQpub3cgPC0gU3lzLnRpbWUoKQoKIyBFeHRyYWN0IHRoZSB5ZWFyCnllYXIgPC0gc3Vic3RyKG5vdywgMSwgNCkKcHJpbnQoeWVhcikKCiMgRXh0cmFjdCB0aGUgbW9udGgKbW9udGggPC0gc3Vic3RyKG5vdywgNiwgNykKcHJpbnQobW9udGgpCgojIEV4dHJhY3QgdGhlIGhvdXIgYW5kIG1pbnV0ZXMKaHJfbWluIDwtIGZvcm1hdChub3csICIlSDolTSIpCnByaW50KGhyX21pbikKYGBgCgpPZiBjb3Vyc2UsIHdlIGNvdWxkIGhhdmUgdXNlZCB0aGUgYHN1YnN0cigpYCBmdW5jdGlvbiBmb3IgdGhlICpocl9taW4qIGV4dHJhY3Rpb24gb3IgZXZlbiBhIHJlZ3VsYXIgZXhwcmVzc2lvbi4gVGhlcmUgaXNuJ3QgYSBzaW5nbGUgY29ycmVjdCBhcHByb2FjaDsgaXQgaXMgcHJvZ3JhbW1pbmcgcHJlZmVyZW5jZSBhbmQgZWFzZSBvZiBjb21wcmVoZW5zaWJpbGl0eS4KCkFuIGFsdGVybmF0aXZlIGZvciBwYXJzaW5nIGZvcm1hdHRlZCBkYXRlIGFuZCB0aW1lIHN0cmluZyBpcyB0aGUgYHN0cnB0aW1lKClgIGZ1bmN0aW9uLiBTaW1pbGFyIHRvIHRoZSBgZm9ybWF0KClgIGZ1bmN0aW9uIHNob3duIGJlbG93LCB0aGUgZm9ybWF0cyBtdXN0IGFkaGVyZSB0byBzcGVjaWZpYyBjb2Rlcywgc3VjaCBhcyBgJVlgIGZvciB0aGUgeWVhciwgYCVtYCBmb3IgdGhlIG1vbnRoLCBhbmQgYCVkYCBmb3IgdGhlIGRheS4KCmBgYHtyfQojIFBhcnNpbmcgYSBjdXN0b20gZGF0ZS10aW1lIHN0cmluZwpkYXRldGltZV9zdHIgPC0gIjIzLTAxLTIwMjUgMTQ6MzA6MDAiCnBhcnNlZF9kYXRldGltZSA8LSBzdHJwdGltZShkYXRldGltZV9zdHIsIGZvcm1hdCA9ICIlZC0lbS0lWSAlSDolTTolUyIpCnByaW50KHBhcnNlZF9kYXRldGltZSkKYGBgCgojIyMgYGZvcm1hdGAgRnVuY3Rpb24KClRoZSBgZm9ybWF0KClgIGZ1bmN0aW9uIGluIFIgaXMgYSBvZnRlbiB1c2VkIHRvIGZvcm1hdCBhbmQgZXh0cmFjdCBjb21wb25lbnRzIGZyb20gZGF0ZSBhbmQgdGltZSBvYmplY3RzLiBJdCBhbGxvd3MgeW91IHRvIGNvbnZlcnQgYERhdGVgIG9yIGBQT1NJWHRgIG9iamVjdHMgaW50byBjaGFyYWN0ZXIgc3RyaW5ncyB3aXRoIGN1c3RvbWl6ZWQgZm9ybWF0cywgc3VpdGFibGUgZm9yIGV4dHJhY3Rpbmcgc3BlY2lmaWMgZGF0ZSBvciB0aW1lIGVsZW1lbnRzLgoKVGhlIGJhc2ljIHN5bnRheCBmb3IgZm9ybWF0IGlzIHNob3cgYmVsb3c6CgpgYGAgcgpmb3JtYXQoeCwgZm9ybWF0ID0gIiIsIHR6ID0gIiIsIHVzZXR6ID0gRkFMU0UpCmBgYAoKSGVyZSBpcyBhIGRldGFpbGVkIGV4cGxhbmF0aW9uIG9mIGVhY2ggcGFyYW1ldGVyOgoKMS4gICoqYHhgKio6CiAgICAtICAgVGhlIGlucHV0IGRhdGUgb3IgdGltZSBvYmplY3QsIHN1Y2ggYXMgYSBgRGF0ZWAsIGBQT1NJWGN0YCwgb3IgYFBPU0lYbHRgIG9iamVjdC4gVGhpcyBpcyB0aGUgdmFsdWUgeW91IHdhbnQgdG8gZm9ybWF0LgoyLiAgKipgZm9ybWF0YCoqOgogICAgLSAgIEEgY2hhcmFjdGVyIHN0cmluZyBzcGVjaWZ5aW5nIHRoZSBkZXNpcmVkIG91dHB1dCBmb3JtYXQuIFRoaXMgc3RyaW5nIHVzZXMgc3BlY2lmaWMgcGxhY2Vob2xkZXJzIChmb3JtYXQgY29kZXMpIHRvIHJlcHJlc2VudCBjb21wb25lbnRzIG9mIHRoZSBkYXRlIGFuZCB0aW1lLgogICAgLSAgIENvbW1vbiBmb3JtYXQgY29kZXMgaW5jbHVkZToKICAgICAgICAtICAgKipgJVlgKio6IEZ1bGwgeWVhciAoZS5nLiwgIjIwMjUiKS4KICAgICAgICAtICAgKipgJXlgKio6IExhc3QgdHdvIGRpZ2l0cyBvZiB0aGUgeWVhciAoZS5nLiwgIjI1IikuCiAgICAgICAgLSAgICoqYCVtYCoqOiBNb250aCBhcyBhIHR3by1kaWdpdCBudW1iZXIgKGUuZy4sICIwMSIpLgogICAgICAgIC0gICAqKmAlQmAqKjogRnVsbCBtb250aCBuYW1lIChlLmcuLCAiSmFudWFyeSIpLgogICAgICAgIC0gICAqKmAlYmAqKjogQWJicmV2aWF0ZWQgbW9udGggbmFtZSAoZS5nLiwgIkphbiIpLgogICAgICAgIC0gICAqKmAlZGAqKjogRGF5IG9mIHRoZSBtb250aCBhcyBhIHR3by1kaWdpdCBudW1iZXIgKGUuZy4sICIyMyIpLgogICAgICAgIC0gICAqKmAlSGAqKjogSG91ciBpbiAyNC1ob3VyIGZvcm1hdCAoZS5nLiwgIjE1IikuCiAgICAgICAgLSAgICoqYCVJYCoqOiBIb3VyIGluIDEyLWhvdXIgZm9ybWF0IChlLmcuLCAiMDMiKS4KICAgICAgICAtICAgKipgJU1gKio6IE1pbnV0ZSAoZS5nLiwgIjQ1IikuCiAgICAgICAgLSAgICoqYCVTYCoqOiBTZWNvbmQgKGUuZy4sICIxMiIpLgogICAgICAgIC0gICAqKmAlcGAqKjogQU0vUE0gaW5kaWNhdG9yLgogICAgICAgIC0gICAqKmAlQWAqKjogRnVsbCB3ZWVrZGF5IG5hbWUgKGUuZy4sICJUaHVyc2RheSIpLgogICAgICAgIC0gICAqKmAlYWAqKjogQWJicmV2aWF0ZWQgd2Vla2RheSBuYW1lIChlLmcuLCAiVGh1IikuCiAgICAgICAgLSAgICoqYCVqYCoqOiBEYXkgb2YgdGhlIHllYXIgYXMgYSBudW1iZXIgKGUuZy4sICIwMjMiKS4KICAgICAgICAtICAgKipgJVdgKio6IFdlZWsgbnVtYmVyIG9mIHRoZSB5ZWFyIChzdGFydGluZyB3aXRoIE1vbmRheSBhcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrKS4KICAgICAgICAtICAgKipgJXdgKio6IFdlZWtkYXkgbnVtYmVyICgwID0gU3VuZGF5LCAxID0gTW9uZGF5LCBldGMuKS4KICAgICAgICAtICAgKipgJXpgKio6IFRpbWV6b25lIG9mZnNldCAoZS5nLiwgIi0wNTAwIikuCiAgICAgICAgLSAgICoqYCVaYCoqOiBUaW1lem9uZSBhYmJyZXZpYXRpb24gKGUuZy4sICJVVEMiKS4KMy4gICoqYHR6YCoqOgogICAgLSAgIEEgY2hhcmFjdGVyIHN0cmluZyBzcGVjaWZ5aW5nIHRoZSBkZXNpcmVkIHRpbWUgem9uZSAoZS5nLiwgYCJVVEMiYCwgYCJBbWVyaWNhL05ld19Zb3JrImApLiBJZiBub3QgcHJvdmlkZWQsIHRoZSBzeXN0ZW0ncyBkZWZhdWx0IHRpbWUgem9uZSBpcyB1c2VkLgo0LiAgKipgdXNldHpgKio6CiAgICAtICAgQSBsb2dpY2FsIHZhbHVlIChgVFJVRWAgb3IgYEZBTFNFYCkgdGhhdCBzcGVjaWZpZXMgd2hldGhlciB0byBpbmNsdWRlIHRoZSB0aW1lIHpvbmUgYWJicmV2aWF0aW9uIGluIHRoZSBmb3JtYXR0ZWQgb3V0cHV0LiBUaGlzIGlzIHJlbGV2YW50IGZvciBgUE9TSVh0YCBvYmplY3RzLgoKTGV0J3MgdGFrZSBhIGxvb2sgYXQgc29tZSBleGFtcGxlcy4gWW91IGNhbiBmb3JtYXQgYSBgRGF0ZWAgb2JqZWN0IHRvIGV4dHJhY3Qgb3IgZGlzcGxheSBzcGVjaWZpYyBjb21wb25lbnRzLgoKYGBge3J9CiMgQ3JlYXRpbmcgYSBEYXRlIG9iamVjdApkYXRlX29iaiA8LSBhcy5EYXRlKCIyMDI1LTAxLTIzIikKCiMgRXh0cmFjdGluZyB0aGUgeWVhcgp5ZWFyIDwtIGZvcm1hdChkYXRlX29iaiwgIiVZIikKcHJpbnQoeWVhcikgICMgT3V0cHV0OiAiMjAyNSIKCiMgRXh0cmFjdGluZyB0aGUgbW9udGggYXMgYSBuYW1lCm1vbnRoX25hbWUgPC0gZm9ybWF0KGRhdGVfb2JqLCAiJUIiKQpwcmludChtb250aF9uYW1lKSAgIyBPdXRwdXQ6ICJKYW51YXJ5IgoKIyBFeHRyYWN0aW5nIHRoZSBkYXkgb2YgdGhlIHdlZWsKd2Vla2RheSA8LSBmb3JtYXQoZGF0ZV9vYmosICIlQSIpCnByaW50KHdlZWtkYXkpICAjIE91dHB1dDogIlRodXJzZGF5IgpgYGAKClRoZSBmb3JtYXQoKSBmdW5jdGlvbiBhbHNvIHdvcmtzIHdpdGggYFBPU0lYY3RgIG9iamVjdHMgaW4gYWRkaXRpb24gdG8gYERhdGVgIG9iamVjdHMuCgpgYGB7cn0KIyBDcmVhdGluZyBhIFBPU0lYY3Qgb2JqZWN0CmRhdGV0aW1lX29iaiA8LSBhcy5QT1NJWGN0KCIyMDI1LTAxLTIzIDE1OjQ1OjEyIiwgdHogPSAiVVRDIikKCiMgRXh0cmFjdGluZyB0aGUgaG91cgpob3VyIDwtIGZvcm1hdChkYXRldGltZV9vYmosICIlSCIpCnByaW50KGhvdXIpICAjIE91dHB1dDogIjE1IgoKIyBFeHRyYWN0aW5nIHRoZSBtaW51dGUKbWludXRlIDwtIGZvcm1hdChkYXRldGltZV9vYmosICIlTSIpCnByaW50KG1pbnV0ZSkgICMgT3V0cHV0OiAiNDUiCgojIEV4dHJhY3RpbmcgdGhlIHRpbWV6b25lCnRpbWV6b25lIDwtIGZvcm1hdChkYXRldGltZV9vYmosICIlWiIpCnByaW50KHRpbWV6b25lKSAgIyBPdXRwdXQ6ICJVVEMiCmBgYAoKSGVyZSBpcyBhIG1vcmUgZWxhYm9yYXRlIGV4YW1wbGUgaW4gd2hpY2ggd2UgY29tYmluZSBkaWZmZXJlbnQgY29tcG9uZW50cyB0byBjcmVhdGUgY3VzdG9tIGRhdGUtdGltZSBzdHJpbmdzLgoKYGBge3J9CiMgQ3VzdG9tIGZvcm1hdHRlZCBzdHJpbmcKY3VzdG9tX2Zvcm1hdCA8LSBmb3JtYXQoZGF0ZXRpbWVfb2JqLCAiJWQtJWItJVkgJUk6JU0gJXAgKCVaKSIpCnByaW50KGN1c3RvbV9mb3JtYXQpICAjIE91dHB1dDogIjIzLUphbi0yMDI1IDAzOjQ1IFBNIChVVEMpIgpgYGAKClRoZSBgdHpgIHBhcmFtZXRlciBhbGxvd3MgeW91IHRvIGZvcm1hdCB0aGUgZGF0ZS10aW1lIGluIGEgc3BlY2lmaWMgdGltZSB6b25lIGFsbG93aW5nIGZvciBjb252ZXJzaW9uIHRvIGEgY29tbW9uIHRpbWUgem9uZSBvciB0byBsb2NhbGl6ZSB0aW1lcy4KCmBgYHtyfQojIEZvcm1hdHRpbmcgd2l0aCBhIHNwZWNpZmljIHRpbWUgem9uZQpkYXRldGltZV9vYmpfdHogPC0gZm9ybWF0KGRhdGV0aW1lX29iaiwgIiVZLSVtLSVkICVIOiVNOiVTICVaIiwgdHogPSAiQW1lcmljYS9OZXdfWW9yayIpCnByaW50KGRhdGV0aW1lX29ial90eikgICMgT3V0cHV0OiAiMjAyNS0wMS0yMyAxMDo0NToxMiBFU1QiCmBgYAoKVGhlIGB1c2V0emAgcGFyYW1ldGVyIGNhbiBiZSB1c2VkIHRvIGNvbnRyb2wgd2hldGhlciB0aGUgdGltZSB6b25lIGlzIGRpc3BsYXllZCBpbiB0aGUgb3V0cHV0LgoKYGBge3J9CiMgSW5jbHVkaW5nIHRoZSB0aW1lIHpvbmUKZm9ybWF0dGVkX3dpdGhfdHogPC0gZm9ybWF0KGRhdGV0aW1lX29iaiwgIiVZLSVtLSVkICVIOiVNOiVTIiwgdXNldHogPSBUUlVFKQpwcmludChmb3JtYXR0ZWRfd2l0aF90eikgICMgT3V0cHV0OiAiMjAyNS0wMS0yMyAxNTo0NToxMiBVVEMiCgojIEV4Y2x1ZGluZyB0aGUgdGltZSB6b25lCmZvcm1hdHRlZF93aXRob3V0X3R6IDwtIGZvcm1hdChkYXRldGltZV9vYmosICIlWS0lbS0lZCAlSDolTTolUyIsIHVzZXR6ID0gRkFMU0UpCnByaW50KGZvcm1hdHRlZF93aXRob3V0X3R6KSAgIyBPdXRwdXQ6ICIyMDI1LTAxLTIzIDE1OjQ1OjEyIgpgYGAKClRoZSBgZm9ybWF0KClgIGZ1bmN0aW9uIGlzIGEgY29tbW9ubHkgdXNlZCBkYXRlIHBhcnNpbmcgZnVuY3Rpb24gYmVjYXVzZSB5b3UgY2FuOgoKLSAgIGV4dHJhY3Qgc3BlY2lmaWMgZGF0ZSBvciB0aW1lIGVsZW1lbnRzICgqZS5nLiosIHllYXIsIG1vbnRoLCBkYXksIGhvdXIpLgotICAgY3JlYXRlIGN1c3RvbSBkYXRlLXRpbWUgc3RyaW5ncyBmb3IgZGlzcGxheSBvciByZXBvcnRpbmcgcHVycG9zZXMuCi0gICBjb252ZXJ0IGRhdGUtdGltZSBvYmplY3RzIGludG8gY2hhcmFjdGVyIHN0cmluZ3MgZm9yIGxhYmVsaW5nIG9yIGV4cG9ydGluZyBkYXRhLgoKIyMgUGFyc2luZyBEYXRlIFN0cmluZ3MKCkRhdGEgZmlsZXMgb2Z0ZW4gaGF2ZSBkYXRlIGFuZCB0aW1lIHN0YW1wcyBpbiBub24tc3RhbmRhcmQgZm9ybWF0IHdoaWNoIHJlcXVpcmUgdGVzdCBwcm9jZXNzaW5nIGZ1bmN0aW9ucyB0byBleHRyYWN0IHRoZSB2YXJpb3VzIGNvbXBvbmVudHMuIEluIHN1Y2ggc2l0dWF0aW9ucywgdGhlIGBmb3JtYXQoKWAgb3IgYHN0cnB0aW1lKClgIGZ1bmN0aW9ucyBpcyBub3QgYXBwcm9wcmlhdGUgYXMgdGhlIGRhdGUgc3RyaW5ncyBkbyBub3QgY29ycmVzcG9uZCB0byBhIGBEYXRlYCBvciBgUE9TSVhjdGAgZm9ybWF0LgoKYGBge3J9CmQgPC0gIkRlYyAyNCwgMjAyNCIKbW9udGggPC0gc3Vic3RyKGQsIDEsIDMpCmRheSA8LSBzdWJzdHIoZCwgNSwgNikKCm1vbnRocyA8LSBjKCJKYW4iLCAiRmViIiwgIk1hciIsICJBcHIiLCAiTWF5IiwgIkp1biIsIAogICAgICAgICAgICAiSnVsIiwgIkF1ZyIsICJTZXAiLCAiT2N0IiwgIk5vdiIsICJEZWMiKQoKbW9udGhfbnVtIDwtIHdoaWNoKG1vbnRocyA9PSBtb250aCkKCm1vbnRoX2RheSA8LSBwYXN0ZTAobW9udGhfbnVtLCAiLyIsIGRheSkKcHJpbnQobW9udGhfZGF5KQpgYGAKCk9mIGNvdXJzZSwgdGhlIGFib3ZlIGNvZGUgZ2V0cyBhIGJpdCBtb3JlIGNoYWxsZW5naW5nIGlmIHRoZSBlbmNvZGluZyBhbGxvd3MgZm9yICJEZWMgMywgMjAyNCIgYW5kICJBcHIgMTIsIDIwMjQiIGFzIHRoZSBkYXkgaXMgZWl0aGVyIG9uZSBvciB0d28gZGlnaXRzLiBJbiB0aGlzIHNpdHVhdGlvbiBsb29raW5nIGZvciB0aGUgY29tbWEgbWlnaHQgYmUgYmV0dGVyIG9yIGFwcGx5aW5nIGEgcmVndWxhciBleHByZXNzaW9uLiBUaGlzIGNhbiBiZSBmdW4uLi4KCiMjIFRoZSAqKmx1YnJpZGF0ZSoqIFBhY2thZ2UKCldoaWxlIEJhc2UgUiBvZmZlcnMgYSBwbGV0aG9yYSBvZiBmdW5jdGlvbnMsIHRoZSAqKmx1YnJpZGF0ZSoqIHBhY2thZ2Ugc2ltcGxpZmllcyBtYW55IGNvbW1vbiBkYXRlLXRpbWUgb3BlcmF0aW9ucyB3aXRoIHNpbXBsZXItdG8tdXNlIGZ1bmN0aW9ucy4gVGhpcyBwYWNrYWdlIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIHBhcnNpbmcsIGV4dHJhY3RpbmcsIGFuZCBtYW5pcHVsYXRpbmcgZGF0ZS10aW1lIHZhbHVlcy4KClRoZSBgbHVicmlkYXRlYCBwYWNrYWdlIHByb3ZpZGVzIGludHVpdGl2ZSBmdW5jdGlvbnMgbGlrZSBgeW1kKClgLCBgbWR5KClgLCBhbmQgYGRteSgpYCBmb3IgcGFyc2luZyBkYXRlcyBpbiBkaWZmZXJlbnQgZm9ybWF0cy4KCmBgYHtyIHdhcm5pbmc9Rn0KbGlicmFyeShsdWJyaWRhdGUpCgojIFBhcnNpbmcgd2l0aCBsdWJyaWRhdGUKZGF0ZV9wYXJzZWQgPC0geW1kKCIyMDI1LTAxLTIzIikKcHJpbnQoZGF0ZV9wYXJzZWQpCgpkYXRldGltZV9wYXJzZWQgPC0geW1kX2htcygiMjAyNS0wMS0yMyAxNDozMDowMCIpCnByaW50KGRhdGV0aW1lX3BhcnNlZCkKYGBgCgoqKmx1YnJpZGF0ZSoqIG1ha2VzIGl0IGVhc2llciB0byBleHRyYWN0IHNwZWNpZmljIGNvbXBvbmVudHMgb2YgZGF0ZS10aW1lIG9iamVjdHMgdXNpbmcgZnVuY3Rpb25zIGxpa2UgYHllYXIoKWAsIGBtb250aCgpYCwgYW5kIGBkYXkoKWAuIFNvbWUgZXhhbXBsZXMgYXJlIHNob3duIGJlbG93LgoKYGBge3J9CiMgRXh0cmFjdGluZyBjb21wb25lbnRzCnllYXJfdmFsIDwtIHllYXIoZGF0ZXRpbWVfcGFyc2VkKQptb250aF92YWwgPC0gbW9udGgoZGF0ZXRpbWVfcGFyc2VkKQpkYXlfdmFsIDwtIGRheShkYXRldGltZV9wYXJzZWQpCgpwcmludChwYXN0ZSgiWWVhcjoiLCB5ZWFyX3ZhbCwgIk1vbnRoOiIsIG1vbnRoX3ZhbCwgIkRheToiLCBkYXlfdmFsKSkKYGBgCgpBZGRpdGlvbmFsbHksICoqbHVicmlkYXRlKiogc2ltcGxpZmllcyBkYXRlLXRpbWUgYXJpdGhtZXRpYy4gRm9yIGV4YW1wbGUsIHlvdSBjb3JyZWN0bHkgY2FuIGFkZCBtb250aHMsIGRheXMsIG9yIHllYXJzIHRvIGEgZGF0ZS4KCmBgYHtyfQojIEFkZGluZyBkdXJhdGlvbgpuZXdfZGF0ZSA8LSBkYXRlX3BhcnNlZCArIG1vbnRocygyKQpwcmludChuZXdfZGF0ZSkKCiMgQ29tcHV0aW5nIGRpZmZlcmVuY2VzCmRhdGVfZGlmZiA8LSBhcy5kdXJhdGlvbihpbnRlcnZhbChkYXRlX3BhcnNlZCwgbmV3X2RhdGUpKQpwcmludChkYXRlX2RpZmYpCmBgYAoKIyMgU3RhbmRhcmRzOiBQT1NJWCBhbmQgSVNPIDg2MDEKCiMjIyBQT1NJWAoKUE9TSVggKFBvcnRhYmxlIE9wZXJhdGluZyBTeXN0ZW0gSW50ZXJmYWNlKSBkZWZpbmVzIGhvdyBkYXRlLXRpbWUgdmFsdWVzIGFyZSByZXByZXNlbnRlZCBhbmQgbWFuaXB1bGF0ZWQgaW4gVW5peC1saWtlIHN5c3RlbXMuIEluIFIsIFBPU0lYY3QgYW5kIFBPU0lYbHQgYWRoZXJlIHRvIHRoaXMgc3RhbmRhcmQuCgojIyMgSVNPIDg2MDEKCklTTyA4NjAxIGlzIGFuIGludGVybmF0aW9uYWwgc3RhbmRhcmQgZm9yIHJlcHJlc2VudGluZyBkYXRlcyBhbmQgdGltZXMgaW4gYSBjb25zaXN0ZW50LCB1bmFtYmlndW91cyBmb3JtYXQuIEl0IHVzZXMgZm9ybWF0cyBzdWNoIGFzICpZWVlZLU1NLUREKiBmb3IgZGF0ZXMgYW5kICpZWVlZLU1NLUREVEhIOk1NOlNTKiBmb3IgZGF0ZS10aW1lIHZhbHVlcy4gVGhlIGZ1bGwgZGF0ZXRpbWUgc3RhbXAgc3RydWN0dXJlIGlzIHNob3duIGluIHRoZSBkaWFncmFtIGJlbG93LiBOb3RpY2UgdGhlIHVzZSBvZiAnLScgYXMgdGhlIHNlcGFyYXRvciBmb3IgdGhlIGRhdGUgZWxlbWVudHMgYW5kICc6JyBhcyB0aGUgc2VwYXJhdG9yIGZvciB0aGUgdGltZSBlbGVtZW50cy4gQSBkb3QgKC4pIHNlcGFyYXRlcyB0aGUgbWlsbGlzZWNvbmRzLiBUaGUgaG91cnMgYXJlIGluIDI0LWhvdXIgZm9ybWF0IC0tIHRoZXJlIGlzIG5vIGFjY29tbW9kYXRpb24gZm9yIGFuICdhbScgb3IgJ3BtJyBpbmRpY2F0b3IuCgohW10oSU1BR0VTL0lTTzg2MDEtRGF0ZUZvcm1hdERpYWdyYW0ucG5nKXt3aWR0aD0iNTAlIn0KClRoZSBmdW5jdGlvbnMgb2YgKipsdWJyaWRhdGUqKiBhdXRvbWF0aWNhbGx5IHJlY29nbml6ZSBhbmQgaGFuZGxlIElTTyA4NjAxIGZvcm1hdHRlZCBkYXRlIGFuZCB0aW1lIHN0cmluZ3MuCgojIyBTdW1tYXJ5CgpJbiB0aGlzIGxlc3Nvbiwgd2UgZXhwbG9yZWQgdGhlIGZvdW5kYXRpb25hbCB0b29scyBpbiBCYXNlIFIgZm9yIHdvcmtpbmcgd2l0aCBkYXRlIGFuZCB0aW1lIG9iamVjdHMsIGluY2x1ZGluZyBgRGF0ZWAsIGBQT1NJWGN0YCwgYW5kIGBQT1NJWGx0YC4gV2UgYWxzbyBpbnRyb2R1Y2VkIHRoZSAqKmx1YnJpZGF0ZSoqIHBhY2thZ2UsIHdoaWNoIHNpbXBsaWZpZXMgcGFyc2luZywgZXh0cmFjdGlvbiwgYW5kIGNvbXB1dGF0aW9uLiBBbG9uZyB0aGUgd2F5LCB3ZSBkaXNjdXNzZWQgaW1wb3J0YW50IHN0YW5kYXJkcyBsaWtlIFBPU0lYIGFuZCBJU08gODYwMSwgd2hpY2ggZW5zdXJlIGNvbnNpc3RlbmN5IGluIGRhdGUtdGltZSByZXByZXNlbnRhdGlvbnMsIHBhcnRpY3VsYXJseSBhY3Jvc3MgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGFuZCBkYXRhYmFzZXMuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIEZpbGVzICYgUmVzb3VyY2VzCgpgYGB7ciB6aXBGaWxlcywgZWNobz1GQUxTRX0KemlwTmFtZSA9IHNwcmludGYoIkxlc3NvbkZpbGVzLSVzLSVzLnppcCIsIAogICAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwKICAgICAgICAgICAgICAgICBwYXJhbXMkbnVtYmVyKQoKdGV4dEFMaW5rID0gcGFzdGUwKCJBbGwgRmlsZXMgZm9yIExlc3NvbiAiLCAKICAgICAgICAgICAgICAgcGFyYW1zJGNhdGVnb3J5LCIuIixwYXJhbXMkbnVtYmVyKQoKIyBkb3dubG9hZEZpbGVzTGluaygpIGlzIGluY2x1ZGVkIGZyb20gX2luc2VydDJEQi5SCmtuaXRyOjpyYXdfaHRtbChkb3dubG9hZEZpbGVzTGluaygiLiIsIHppcE5hbWUsIHRleHRBTGluaykpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBSZWZlcmVuY2VzCgpObyByZWZlcmVuY2VzLgoKIyMgRXJyYXRhCgpbTGV0IHVzIGtub3ddKGh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS8yMTIxODcwNzI3ODQxNTcpe3RhcmdldD0iX2JsYW5rIn0uCg==