Introduction

Dates are a separate data type in R and SQL. A date object can be used in “date aware” calculations, for example in BETWEEN clauses in SQL. Dates have a different format in R and SQL. A text column or character variable, even if they are formatted like a date, are not actual dates.

Converting Text to Date Objects

To convert text to a date object in R, the text string must be in the format YYYY-MM-DD or YYYY/MM/DD.

s2 <- "2021-02-15"
d1 <- as.Date(s2)

print(d1)
## [1] "2021-02-15"

Note that the class (type) of the above variable d1 is of type Date.

Alternatively, the date can be specified as YYYY/MM/DD as demonstrated below.

s3 <- "2019/06/30"
d2 <- as.Date(s3)

print(d2)
## [1] "2019-06-30"

Date Format Specification

To convert text to a date object in R, the text string must be in the format YYYY-MM-DD unless the format parameter is specified.

as.Date("07/04/20", format = "%m/%d/%y")
## [1] "2020-07-04"
as.Date("JUL 04 2021", format = "%b %d %Y")
## [1] "2021-07-04"
as.Date("February 11 80", format = "%B %d %y")
## [1] "1980-02-11"

Here are the various date format specifications:

Symbol Meaning Example
%d day as a number (01-31) 06
%a abbreviated weekday Mon
%A full weekday Monday
%m month (00-12) 11
%b abbreviated month Nov
%B full month March
%y two-digit year 20
%Y four-digit year 2021

Current System Time and Date

To get the current date from the system’s clock, use Sys.Date(). To get the current date and time, use date().

# get current date and time
date()
## [1] "Wed Feb 14 09:48:52 2024"
# get current date only as YYYY-MM-DD
Sys.Date()
## [1] "2024-02-14"

lubridate Package

The lubridate package has many more functions for converting from various other formats, but these are addressed in a different tutorial (See Also).

Dates in SQLite

Let’s create a simple in-memory database with one table (txns), three columns, where the first column in an integer primary key, the second is a date, and the third is text.

library(RSQLite)
db <- dbConnect(RSQLite::SQLite(), ":memory:")
create table txns (
  tid integer primary key,
  tdate date not null,
  tprod text
)

Now that the table is created, let’s insert some values to ensure that the table definition is correct and we can retrieve the data with their correct data type.

insert into txns values 
(100, '2022-03-31', 'Alvarex'),
(200, '2022-03-30', 'Prosilvas'),
(300, '2022-03-30', 'Alvarex'),
(400, '2022-02-09', 'Kitomaron'),
(500, '2022-01-14', 'Blevarex');

Let’s quickly retrieve all rows to ensure they are in the database.

select * from txns;
Table 1: 5 records
tid tdate tprod
100 2022-03-31 Alvarex
200 2022-03-30 Prosilvas
300 2022-03-30 Alvarex
400 2022-02-09 Kitomaron
500 2022-01-14 Blevarex

Indeed, they are. But note that the date column tdate is returned as text (<chr>). To determine if SQLite actually stored them as type date, we can run a SQL query that requires date column type.

select * 
  from txns
 where tdate between '2022-03-01' and '2022-03-31'
Table 2: 3 records
tid tdate tprod
100 2022-03-31 Alvarex
200 2022-03-30 Prosilvas
300 2022-03-30 Alvarex

The above query works, so we can be confident that SQLite stored the dates correctly even though R convert them to text.

And, finally, let’s retrieve some data into a data frame and list the data along with the types of the columns in the data frame. Recall that all result sets of queries are tables.

rs <- dbGetQuery(db, 'select * from txns')

print(rs)
##   tid      tdate     tprod
## 1 100 2022-03-31   Alvarex
## 2 200 2022-03-30 Prosilvas
## 3 300 2022-03-30   Alvarex
## 4 400 2022-02-09 Kitomaron
## 5 500 2022-01-14  Blevarex

Note that the date column came back from the query as text; the data frame has the data type <chr> for the tdate column. To use them as dates, you need to coerce the column type of the data frame to Date.

rs$tdate <- as.Date(rs$tdate)

print(rs)
##   tid      tdate     tprod
## 1 100 2022-03-31   Alvarex
## 2 200 2022-03-30 Prosilvas
## 3 300 2022-03-30   Alvarex
## 4 400 2022-02-09 Kitomaron
## 5 500 2022-01-14  Blevarex

Notice that now the tdate column is of the correct R Date type and we can apply R date functions to that column.

Saving Date Data to SQLite

In the above discussion, we saw that SQL dates are converted to text when retrieved into a data frame and an explicit coercion is required if we want to treat dates as actual R Date objects. A similar issue occurs when we save Date columns in data frames to R. We will demonstrate the issues by creating a data frame which we will then save into a new table in SQLite using dbWriteTable() and then we will save the same data frame to an already created table, again using dbWriteTable(). The difference is that in one case, the table does not yet exist, while in the other it does.

We will use the data frame rs that we retrieved above. To review, we had to coerce the data column explicitly to a Date object. As you can see, the data frame has three columns of types int (integer), date (Date) and chr (text characters), respectively.

print(rs)
##   tid      tdate     tprod
## 1 100 2022-03-31   Alvarex
## 2 200 2022-03-30 Prosilvas
## 3 300 2022-03-30   Alvarex
## 4 400 2022-02-09 Kitomaron
## 5 500 2022-01-14  Blevarex

Let’s save this entire data frame to a new table in the in-memory SQLite database and then inspect the data types of the columns of the table in the database.

dbWriteTable(db, 'newTxns', rs)

Now, if we retrieve we know from the experiments above that the date column will be text, but we want to know what the database stores them as. The code below uses a PRAGMA to query the database itself.

PRAGMA table_info(newTxns);
Table 3: 3 records
cid name type notnull dflt_value pk
0 tid INTEGER 0 NA 0
1 tdate REAL 0 NA 0
2 tprod TEXT 0 NA 0

Let’s compare that to the structure of a table that we create manually.

create table newManTxns (
  tid integer primary key,
  tdate date not null,
  tprod text
)
PRAGMA table_info(newManTxns);
Table 4: 3 records
cid name type notnull dflt_value pk
0 tid INTEGER 0 NA 1
1 tdate date 1 NA 0
2 tprod TEXT 0 NA 0

Notice how the table created by dbWriteTable() has REAL as the data type for the tdate column while the manually created table has the correct SQL date data type.

So, we know that saving a data frame to SQLite will change the date column data type from Date to REAL – not very friendly and useful. Let’s see what happens when we write the data frame to an existing table. As a reminder, the columns of the data frame must be in the same order as in the table definition. Because, the table already exists, we need to specify append=T; be careful not to specify overwrite=T as that will wipe out the table and re-create it.

dbWriteTable(db, 'newManTxns', rs, append=T)

And, again, let’s inspect the table.

PRAGMA table_info(newManTxns);
Table 5: 3 records
cid name type notnull dflt_value pk
0 tid INTEGER 0 NA 1
1 tdate date 1 NA 0
2 tprod TEXT 0 NA 0

Now, it has the correct data type. Of course, let’s check the data itself, too:

select * from newManTxns;
Table 6: 5 records
tid tdate tprod
100 19082 Alvarex
200 19081 Prosilvas
300 19081 Alvarex
400 19032 Kitomaron
500 19006 Blevarex

The tade column has an int data type, but let’s be sure that is correct in the database. We’ll run the same query as we did above that requires the data to be of a date type.

select * 
  from newManTxns
 where tdate between '2022-03-01' and '2022-03-31'
Table 7: 0 records
tid tdate tprod

And, as you can see, that did not work – which implies that R or SQLite modified the data and that a Date object is not correctly written to a SQLite database to a date column.

The final experiment uses an R data frame that has the date as text and writes it to a table in the database that has a date column.

We need to first remove all rows from the newManTxns table so we can work with an empty table.

delete from newManTxns;
rs2 <- dbGetQuery(db, 'select * from txns')

print(rs2)
##   tid      tdate     tprod
## 1 100 2022-03-31   Alvarex
## 2 200 2022-03-30 Prosilvas
## 3 300 2022-03-30   Alvarex
## 4 400 2022-02-09 Kitomaron
## 5 500 2022-01-14  Blevarex

So, the data frame rs2 has dates from the database as characters.

dbWriteTable(db, 'newManTxns', rs2, append=T)

Let’s look at the data in the database first:

select * from newManTxns;
Table 8: 5 records
tid tdate tprod
100 2022-03-31 Alvarex
200 2022-03-30 Prosilvas
300 2022-03-30 Alvarex
400 2022-02-09 Kitomaron
500 2022-01-14 Blevarex

And, finally, let’s run the date query again:

select * 
  from newManTxns
 where tdate between '2022-03-01' and '2022-03-31'
Table 9: 3 records
tid tdate tprod
100 2022-03-31 Alvarex
200 2022-03-30 Prosilvas
300 2022-03-30 Alvarex

Now it worked. So what did we learn? Date columns in data frames do not correctly map to date columns in the database. In order for dbWriteTable() to properly write dates to date columns in the database, the column for the dates must be characters in R; they cannot be Date objects. Counterinituitive, but that’s the way it works.

Understanding R to SQL Data Mappings

To understand how R maps objects to SQL, we can use the dbDataType() function.

dbDataType(db, rs$tdate)
## [1] "REAL"

This tells us R will convert the column to REAL when written to the database, which is what we saw above.

Conclusion

Dates must be properly encoded for them to be processed correctly. R and SQL use dates differently and converting between the two formats require care. Date columns in data frames do not get converted properly to columns of type date in SQLite.

Tutorial

The video tutorial demonstrates the constructs introduced in this lesson.


Files & Resources

All Files for Lesson 6.306

Errata

None collected yet. Let us know.

LS0tDQp0aXRsZTogIkRhdGVzIGluIFIgYW5kIFNRTGl0ZSINCnBhcmFtczoNCiAgY2F0ZWdvcnk6IDYNCiAgbnVtYmVyOiAzMDYNCiAgdGltZTogNjANCiAgbGV2ZWw6IGJlZ2lubmVyDQogIHRhZ3M6ICJyLGRhdGVzLHNxbCxzcWxpdGUsbHVicmlkYXRlIg0KICBkZXNjcmlwdGlvbjogIlJlYWRpbmcgZGF0ZXMgZnJvbSByYXcgZGF0YSBhbmQgdXNpbmcgdGhlbSBpbiBSIGFuZCBzYXZpbmcgdGhlbQ0KICAgICAgICAgICAgICAgIG9yIGxvYWRpbmcgdGhlbSBmcm9tIFNRTGl0ZSBjYW4gYmUgY2hhbGxlbmdpbmcuIFRoaXMgdHV0b3JpYWwNCiAgICAgICAgICAgICAgICBleHBsYWlucyBob3cgdG8gd29yayB3aXRoIGRhdGVzIGluIFIsIFNRTCwgYW5kIFNRTGl0ZS4iDQpkYXRlOiAiPHNtYWxsPmByIFN5cy5EYXRlKClgPC9zbWFsbD4iDQphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iDQplbWFpbDogIm0uc2NoZWRsYmF1ZXJAbmV1LmVkdSINCmFmZmlsaXRhdGlvbjogIk5vcnRoZWFzdGVybiBVbml2ZXJzaXR5Ig0Kb3V0cHV0OiANCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgIGhpZ2hsaWdodDogdGFuZ28NCi0tLQ0KDQotLS0NCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iDQotLS0NCg0KYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9DQpgYGANCg0KIyMgSW50cm9kdWN0aW9uDQoNCkRhdGVzIGFyZSBhIHNlcGFyYXRlIGRhdGEgdHlwZSBpbiBSIGFuZCBTUUwuIEEgZGF0ZSBvYmplY3QgY2FuIGJlIHVzZWQgaW4gImRhdGUgYXdhcmUiIGNhbGN1bGF0aW9ucywgZm9yIGV4YW1wbGUgaW4gKkJFVFdFRU4qIGNsYXVzZXMgaW4gU1FMLiBEYXRlcyBoYXZlIGEgZGlmZmVyZW50IGZvcm1hdCBpbiBSIGFuZCBTUUwuIEEgdGV4dCBjb2x1bW4gb3IgY2hhcmFjdGVyIHZhcmlhYmxlLCBldmVuIGlmIHRoZXkgYXJlIGZvcm1hdHRlZCBsaWtlIGEgZGF0ZSwgYXJlIG5vdCBhY3R1YWwgZGF0ZXMuDQoNCiMjIENvbnZlcnRpbmcgVGV4dCB0byBEYXRlIE9iamVjdHMNCg0KVG8gY29udmVydCB0ZXh0IHRvIGEgZGF0ZSBvYmplY3QgaW4gUiwgdGhlIHRleHQgc3RyaW5nIG11c3QgYmUgaW4gdGhlIGZvcm1hdCAqWVlZWS1NTS1ERCogb3IgKllZWVkvTU0vREQqLg0KDQpgYGB7cn0NCnMyIDwtICIyMDIxLTAyLTE1Ig0KZDEgPC0gYXMuRGF0ZShzMikNCg0KcHJpbnQoZDEpDQpgYGANCg0KTm90ZSB0aGF0IHRoZSAqY2xhc3MqICh0eXBlKSBvZiB0aGUgYWJvdmUgdmFyaWFibGUgKmQxKiBpcyBvZiB0eXBlIGByIGNsYXNzKGQxKWAuDQoNCkFsdGVybmF0aXZlbHksIHRoZSBkYXRlIGNhbiBiZSBzcGVjaWZpZWQgYXMgKllZWVkvTU0vREQqIGFzIGRlbW9uc3RyYXRlZCBiZWxvdy4NCg0KYGBge3J9DQpzMyA8LSAiMjAxOS8wNi8zMCINCmQyIDwtIGFzLkRhdGUoczMpDQoNCnByaW50KGQyKQ0KYGBgDQoNCiMjIyBEYXRlIEZvcm1hdCBTcGVjaWZpY2F0aW9uDQoNClRvIGNvbnZlcnQgdGV4dCB0byBhIGRhdGUgb2JqZWN0IGluIFIsIHRoZSB0ZXh0IHN0cmluZyBtdXN0IGJlIGluIHRoZSBmb3JtYXQgKllZWVktTU0tREQqIHVubGVzcyB0aGUgKmZvcm1hdCogcGFyYW1ldGVyIGlzIHNwZWNpZmllZC4NCg0KYGBge3J9DQphcy5EYXRlKCIwNy8wNC8yMCIsIGZvcm1hdCA9ICIlbS8lZC8leSIpDQphcy5EYXRlKCJKVUwgMDQgMjAyMSIsIGZvcm1hdCA9ICIlYiAlZCAlWSIpDQphcy5EYXRlKCJGZWJydWFyeSAxMSA4MCIsIGZvcm1hdCA9ICIlQiAlZCAleSIpDQpgYGANCg0KSGVyZSBhcmUgdGhlIHZhcmlvdXMgZGF0ZSAqZm9ybWF0KiBzcGVjaWZpY2F0aW9uczoNCg0KfCBTeW1ib2wgfCBNZWFuaW5nICAgICAgICAgICAgICAgICB8IEV4YW1wbGUgfA0KfC0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tfA0KfCAlZCAgICAgfCBkYXkgYXMgYSBudW1iZXIgKDAxLTMxKSB8IDA2ICAgICAgfA0KfCAlYSAgICAgfCBhYmJyZXZpYXRlZCB3ZWVrZGF5ICAgICB8IE1vbiAgICAgfA0KfCAlQSAgICAgfCBmdWxsIHdlZWtkYXkgICAgICAgICAgICB8IE1vbmRheSAgfA0KfCAlbSAgICAgfCBtb250aCAoMDAtMTIpICAgICAgICAgICB8IDExICAgICAgfA0KfCAlYiAgICAgfCBhYmJyZXZpYXRlZCBtb250aCAgICAgICB8IE5vdiAgICAgfA0KfCAlQiAgICAgfCBmdWxsIG1vbnRoICAgICAgICAgICAgICB8IE1hcmNoICAgfA0KfCAleSAgICAgfCB0d28tZGlnaXQgeWVhciAgICAgICAgICB8IDIwICAgICAgfA0KfCAlWSAgICAgfCBmb3VyLWRpZ2l0IHllYXIgICAgICAgICB8IDIwMjEgICAgfA0KDQojIyBDdXJyZW50IFN5c3RlbSBUaW1lIGFuZCBEYXRlDQoNClRvIGdldCB0aGUgY3VycmVudCBkYXRlIGZyb20gdGhlIHN5c3RlbSdzIGNsb2NrLCB1c2UgPGNvZGU+U3lzLkRhdGUoKTwvY29kZT4uIFRvIGdldCB0aGUgY3VycmVudCBkYXRlIGFuZCB0aW1lLCB1c2UgPGNvZGU+ZGF0ZSgpPC9jb2RlPi4NCg0KYGBge3J9DQojIGdldCBjdXJyZW50IGRhdGUgYW5kIHRpbWUNCmRhdGUoKQ0KDQojIGdldCBjdXJyZW50IGRhdGUgb25seSBhcyBZWVlZLU1NLUREDQpTeXMuRGF0ZSgpDQpgYGANCg0KIyMgKipsdWJyaWRhdGUqKiBQYWNrYWdlDQoNClRoZSAqKmx1YnJpZGF0ZSoqIHBhY2thZ2UgaGFzIG1hbnkgbW9yZSBmdW5jdGlvbnMgZm9yIGNvbnZlcnRpbmcgZnJvbSB2YXJpb3VzIG90aGVyIGZvcm1hdHMsIGJ1dCB0aGVzZSBhcmUgYWRkcmVzc2VkIGluIGEgZGlmZmVyZW50IHR1dG9yaWFsIChbU2VlIEFsc29dKCNTZWVfQWxzbykpLg0KDQojIyBEYXRlcyBpbiBTUUxpdGUNCg0KTGV0J3MgY3JlYXRlIGEgc2ltcGxlIGluLW1lbW9yeSBkYXRhYmFzZSB3aXRoIG9uZSB0YWJsZSAoKnR4bnMqKSwgdGhyZWUgY29sdW1ucywgd2hlcmUgdGhlIGZpcnN0IGNvbHVtbiBpbiBhbiBpbnRlZ2VyIHByaW1hcnkga2V5LCB0aGUgc2Vjb25kIGlzIGEgZGF0ZSwgYW5kIHRoZSB0aGlyZCBpcyB0ZXh0Lg0KDQpgYGB7cn0NCmxpYnJhcnkoUlNRTGl0ZSkNCmRiIDwtIGRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgIjptZW1vcnk6IikNCmBgYA0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpjcmVhdGUgdGFibGUgdHhucyAoDQogIHRpZCBpbnRlZ2VyIHByaW1hcnkga2V5LA0KICB0ZGF0ZSBkYXRlIG5vdCBudWxsLA0KICB0cHJvZCB0ZXh0DQopDQpgYGANCg0KTm93IHRoYXQgdGhlIHRhYmxlIGlzIGNyZWF0ZWQsIGxldCdzIGluc2VydCBzb21lIHZhbHVlcyB0byBlbnN1cmUgdGhhdCB0aGUgdGFibGUgZGVmaW5pdGlvbiBpcyBjb3JyZWN0IGFuZCB3ZSBjYW4gcmV0cmlldmUgdGhlIGRhdGEgd2l0aCB0aGVpciBjb3JyZWN0IGRhdGEgdHlwZS4NCg0KYGBge3NxbCBjb25uZWN0aW9uPWRifQ0KaW5zZXJ0IGludG8gdHhucyB2YWx1ZXMgDQooMTAwLCAnMjAyMi0wMy0zMScsICdBbHZhcmV4JyksDQooMjAwLCAnMjAyMi0wMy0zMCcsICdQcm9zaWx2YXMnKSwNCigzMDAsICcyMDIyLTAzLTMwJywgJ0FsdmFyZXgnKSwNCig0MDAsICcyMDIyLTAyLTA5JywgJ0tpdG9tYXJvbicpLA0KKDUwMCwgJzIwMjItMDEtMTQnLCAnQmxldmFyZXgnKTsNCg0KYGBgDQoNCkxldCdzIHF1aWNrbHkgcmV0cmlldmUgYWxsIHJvd3MgdG8gZW5zdXJlIHRoZXkgYXJlIGluIHRoZSBkYXRhYmFzZS4NCg0KYGBge3NxbCBjb25uZWN0aW9uPWRifQ0Kc2VsZWN0ICogZnJvbSB0eG5zOw0KYGBgDQoNCkluZGVlZCwgdGhleSBhcmUuIEJ1dCBub3RlIHRoYXQgdGhlIGRhdGUgY29sdW1uICp0ZGF0ZSogaXMgcmV0dXJuZWQgYXMgdGV4dCAoKlw8Y2hyXD4qKS4gVG8gZGV0ZXJtaW5lIGlmIFNRTGl0ZSBhY3R1YWxseSBzdG9yZWQgdGhlbSBhcyB0eXBlICpkYXRlKiwgd2UgY2FuIHJ1biBhIFNRTCBxdWVyeSB0aGF0IHJlcXVpcmVzIGRhdGUgY29sdW1uIHR5cGUuDQoNCmBgYHtzcWwgY29ubmVjdGlvbj1kYn0NCnNlbGVjdCAqIA0KICBmcm9tIHR4bnMNCiB3aGVyZSB0ZGF0ZSBiZXR3ZWVuICcyMDIyLTAzLTAxJyBhbmQgJzIwMjItMDMtMzEnDQpgYGANCg0KVGhlIGFib3ZlIHF1ZXJ5IHdvcmtzLCBzbyB3ZSBjYW4gYmUgY29uZmlkZW50IHRoYXQgU1FMaXRlIHN0b3JlZCB0aGUgZGF0ZXMgY29ycmVjdGx5IGV2ZW4gdGhvdWdoIFIgY29udmVydCB0aGVtIHRvIHRleHQuDQoNCkFuZCwgZmluYWxseSwgbGV0J3MgcmV0cmlldmUgc29tZSBkYXRhIGludG8gYSBkYXRhIGZyYW1lIGFuZCBsaXN0IHRoZSBkYXRhIGFsb25nIHdpdGggdGhlIHR5cGVzIG9mIHRoZSBjb2x1bW5zIGluIHRoZSBkYXRhIGZyYW1lLiBSZWNhbGwgdGhhdCBhbGwgcmVzdWx0IHNldHMgb2YgcXVlcmllcyBhcmUgdGFibGVzLg0KDQpgYGB7cn0NCnJzIDwtIGRiR2V0UXVlcnkoZGIsICdzZWxlY3QgKiBmcm9tIHR4bnMnKQ0KDQpwcmludChycykNCmBgYA0KDQpOb3RlIHRoYXQgdGhlIGRhdGUgY29sdW1uIGNhbWUgYmFjayBmcm9tIHRoZSBxdWVyeSBhcyB0ZXh0OyB0aGUgZGF0YSBmcmFtZSBoYXMgdGhlIGRhdGEgdHlwZSAqXDxjaHJcPiogZm9yIHRoZSAqdGRhdGUqIGNvbHVtbi4gVG8gdXNlIHRoZW0gYXMgZGF0ZXMsIHlvdSBuZWVkIHRvIGNvZXJjZSB0aGUgY29sdW1uIHR5cGUgb2YgdGhlIGRhdGEgZnJhbWUgdG8gKkRhdGUqLg0KDQpgYGB7cn0NCnJzJHRkYXRlIDwtIGFzLkRhdGUocnMkdGRhdGUpDQoNCnByaW50KHJzKQ0KYGBgDQoNCk5vdGljZSB0aGF0IG5vdyB0aGUgKnRkYXRlKiBjb2x1bW4gaXMgb2YgdGhlIGNvcnJlY3QgUiAqRGF0ZSogdHlwZSBhbmQgd2UgY2FuIGFwcGx5IFIgZGF0ZSBmdW5jdGlvbnMgdG8gdGhhdCBjb2x1bW4uDQoNCiMjIFNhdmluZyBEYXRlIERhdGEgdG8gU1FMaXRlDQoNCkluIHRoZSBhYm92ZSBkaXNjdXNzaW9uLCB3ZSBzYXcgdGhhdCBTUUwgZGF0ZXMgYXJlIGNvbnZlcnRlZCB0byB0ZXh0IHdoZW4gcmV0cmlldmVkIGludG8gYSBkYXRhIGZyYW1lIGFuZCBhbiBleHBsaWNpdCBjb2VyY2lvbiBpcyByZXF1aXJlZCBpZiB3ZSB3YW50IHRvIHRyZWF0IGRhdGVzIGFzIGFjdHVhbCBSICpEYXRlKiBvYmplY3RzLiBBIHNpbWlsYXIgaXNzdWUgb2NjdXJzIHdoZW4gd2Ugc2F2ZSAqRGF0ZSogY29sdW1ucyBpbiBkYXRhIGZyYW1lcyB0byBSLiBXZSB3aWxsIGRlbW9uc3RyYXRlIHRoZSBpc3N1ZXMgYnkgY3JlYXRpbmcgYSBkYXRhIGZyYW1lIHdoaWNoIHdlIHdpbGwgdGhlbiBzYXZlIGludG8gYSBuZXcgdGFibGUgaW4gU1FMaXRlIHVzaW5nIDxjb2RlPmRiV3JpdGVUYWJsZSgpPC9jb2RlPiBhbmQgdGhlbiB3ZSB3aWxsIHNhdmUgdGhlIHNhbWUgZGF0YSBmcmFtZSB0byBhbiBhbHJlYWR5IGNyZWF0ZWQgdGFibGUsIGFnYWluIHVzaW5nIDxjb2RlPmRiV3JpdGVUYWJsZSgpPC9jb2RlPi4gVGhlIGRpZmZlcmVuY2UgaXMgdGhhdCBpbiBvbmUgY2FzZSwgdGhlIHRhYmxlIGRvZXMgbm90IHlldCBleGlzdCwgd2hpbGUgaW4gdGhlIG90aGVyIGl0IGRvZXMuDQoNCldlIHdpbGwgdXNlIHRoZSBkYXRhIGZyYW1lICpycyogdGhhdCB3ZSByZXRyaWV2ZWQgYWJvdmUuIFRvIHJldmlldywgd2UgaGFkIHRvIGNvZXJjZSB0aGUgZGF0YSBjb2x1bW4gZXhwbGljaXRseSB0byBhICpEYXRlKiBvYmplY3QuIEFzIHlvdSBjYW4gc2VlLCB0aGUgZGF0YSBmcmFtZSBoYXMgdGhyZWUgY29sdW1ucyBvZiB0eXBlcyAqaW50KiAoKmludGVnZXIqKSwgKmRhdGUqICgqRGF0ZSopIGFuZCAqY2hyKiAodGV4dCBjaGFyYWN0ZXJzKSwgcmVzcGVjdGl2ZWx5Lg0KDQpgYGB7cn0NCnByaW50KHJzKQ0KYGBgDQoNCkxldCdzIHNhdmUgdGhpcyBlbnRpcmUgZGF0YSBmcmFtZSB0byBhIG5ldyB0YWJsZSBpbiB0aGUgaW4tbWVtb3J5IFNRTGl0ZSBkYXRhYmFzZSBhbmQgdGhlbiBpbnNwZWN0IHRoZSBkYXRhIHR5cGVzIG9mIHRoZSBjb2x1bW5zIG9mIHRoZSB0YWJsZSBpbiB0aGUgZGF0YWJhc2UuDQoNCmBgYHtyfQ0KZGJXcml0ZVRhYmxlKGRiLCAnbmV3VHhucycsIHJzKQ0KYGBgDQoNCk5vdywgaWYgd2UgcmV0cmlldmUgd2Uga25vdyBmcm9tIHRoZSBleHBlcmltZW50cyBhYm92ZSB0aGF0IHRoZSBkYXRlIGNvbHVtbiB3aWxsIGJlIHRleHQsIGJ1dCB3ZSB3YW50IHRvIGtub3cgd2hhdCB0aGUgZGF0YWJhc2Ugc3RvcmVzIHRoZW0gYXMuIFRoZSBjb2RlIGJlbG93IHVzZXMgYSAqUFJBR01BKiB0byBxdWVyeSB0aGUgZGF0YWJhc2UgaXRzZWxmLg0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpQUkFHTUEgdGFibGVfaW5mbyhuZXdUeG5zKTsNCmBgYA0KDQpMZXQncyBjb21wYXJlIHRoYXQgdG8gdGhlIHN0cnVjdHVyZSBvZiBhIHRhYmxlIHRoYXQgd2UgY3JlYXRlIG1hbnVhbGx5Lg0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpjcmVhdGUgdGFibGUgbmV3TWFuVHhucyAoDQogIHRpZCBpbnRlZ2VyIHByaW1hcnkga2V5LA0KICB0ZGF0ZSBkYXRlIG5vdCBudWxsLA0KICB0cHJvZCB0ZXh0DQopDQpgYGANCg0KYGBge3NxbCBjb25uZWN0aW9uPWRifQ0KUFJBR01BIHRhYmxlX2luZm8obmV3TWFuVHhucyk7DQpgYGANCg0KTm90aWNlIGhvdyB0aGUgdGFibGUgY3JlYXRlZCBieSA8Y29kZT5kYldyaXRlVGFibGUoKTwvY29kZT4gaGFzICpSRUFMKiBhcyB0aGUgZGF0YSB0eXBlIGZvciB0aGUgKnRkYXRlKiBjb2x1bW4gd2hpbGUgdGhlIG1hbnVhbGx5IGNyZWF0ZWQgdGFibGUgaGFzIHRoZSBjb3JyZWN0IFNRTCBkYXRlIGRhdGEgdHlwZS4NCg0KU28sIHdlIGtub3cgdGhhdCBzYXZpbmcgYSBkYXRhIGZyYW1lIHRvIFNRTGl0ZSB3aWxsIGNoYW5nZSB0aGUgZGF0ZSBjb2x1bW4gZGF0YSB0eXBlIGZyb20gKkRhdGUqIHRvICpSRUFMKiAtLSBub3QgdmVyeSBmcmllbmRseSBhbmQgdXNlZnVsLiBMZXQncyBzZWUgd2hhdCBoYXBwZW5zIHdoZW4gd2Ugd3JpdGUgdGhlIGRhdGEgZnJhbWUgdG8gYW4gZXhpc3RpbmcgdGFibGUuIEFzIGEgcmVtaW5kZXIsIHRoZSBjb2x1bW5zIG9mIHRoZSBkYXRhIGZyYW1lIG11c3QgYmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgaW4gdGhlIHRhYmxlIGRlZmluaXRpb24uIEJlY2F1c2UsIHRoZSB0YWJsZSBhbHJlYWR5IGV4aXN0cywgd2UgbmVlZCB0byBzcGVjaWZ5ICphcHBlbmQ9VCo7IGJlIGNhcmVmdWwgbm90IHRvIHNwZWNpZnkgKm92ZXJ3cml0ZT1UKiBhcyB0aGF0IHdpbGwgd2lwZSBvdXQgdGhlIHRhYmxlIGFuZCByZS1jcmVhdGUgaXQuDQoNCmBgYHtyfQ0KZGJXcml0ZVRhYmxlKGRiLCAnbmV3TWFuVHhucycsIHJzLCBhcHBlbmQ9VCkNCmBgYA0KDQpBbmQsIGFnYWluLCBsZXQncyBpbnNwZWN0IHRoZSB0YWJsZS4NCg0KYGBge3NxbCBjb25uZWN0aW9uPWRifQ0KUFJBR01BIHRhYmxlX2luZm8obmV3TWFuVHhucyk7DQpgYGANCg0KTm93LCBpdCBoYXMgdGhlIGNvcnJlY3QgZGF0YSB0eXBlLiBPZiBjb3Vyc2UsIGxldCdzIGNoZWNrIHRoZSBkYXRhIGl0c2VsZiwgdG9vOg0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpzZWxlY3QgKiBmcm9tIG5ld01hblR4bnM7DQpgYGANCg0KVGhlICp0YWRlKiBjb2x1bW4gaGFzIGFuICppbnQqIGRhdGEgdHlwZSwgYnV0IGxldCdzIGJlIHN1cmUgdGhhdCBpcyBjb3JyZWN0IGluIHRoZSBkYXRhYmFzZS4gV2UnbGwgcnVuIHRoZSBzYW1lIHF1ZXJ5IGFzIHdlIGRpZCBhYm92ZSB0aGF0IHJlcXVpcmVzIHRoZSBkYXRhIHRvIGJlIG9mIGEgZGF0ZSB0eXBlLg0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpzZWxlY3QgKiANCiAgZnJvbSBuZXdNYW5UeG5zDQogd2hlcmUgdGRhdGUgYmV0d2VlbiAnMjAyMi0wMy0wMScgYW5kICcyMDIyLTAzLTMxJw0KYGBgDQoNCkFuZCwgYXMgeW91IGNhbiBzZWUsIHRoYXQgZGlkIG5vdCB3b3JrIC0tIHdoaWNoIGltcGxpZXMgdGhhdCBSIG9yIFNRTGl0ZSBtb2RpZmllZCB0aGUgZGF0YSBhbmQgdGhhdCBhICpEYXRlKiBvYmplY3QgaXMgbm90IGNvcnJlY3RseSB3cml0dGVuIHRvIGEgU1FMaXRlIGRhdGFiYXNlIHRvIGEgZGF0ZSBjb2x1bW4uDQoNClRoZSBmaW5hbCBleHBlcmltZW50IHVzZXMgYW4gUiBkYXRhIGZyYW1lIHRoYXQgaGFzIHRoZSBkYXRlIGFzIHRleHQgYW5kIHdyaXRlcyBpdCB0byBhIHRhYmxlIGluIHRoZSBkYXRhYmFzZSB0aGF0IGhhcyBhICpkYXRlKiBjb2x1bW4uDQoNCldlIG5lZWQgdG8gZmlyc3QgcmVtb3ZlIGFsbCByb3dzIGZyb20gdGhlICpuZXdNYW5UeG5zKiB0YWJsZSBzbyB3ZSBjYW4gd29yayB3aXRoIGFuIGVtcHR5IHRhYmxlLg0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpkZWxldGUgZnJvbSBuZXdNYW5UeG5zOw0KYGBgDQoNCmBgYHtyfQ0KcnMyIDwtIGRiR2V0UXVlcnkoZGIsICdzZWxlY3QgKiBmcm9tIHR4bnMnKQ0KDQpwcmludChyczIpDQpgYGANCg0KU28sIHRoZSBkYXRhIGZyYW1lICpyczIqIGhhcyBkYXRlcyBmcm9tIHRoZSBkYXRhYmFzZSBhcyBjaGFyYWN0ZXJzLg0KDQpgYGB7cn0NCmRiV3JpdGVUYWJsZShkYiwgJ25ld01hblR4bnMnLCByczIsIGFwcGVuZD1UKQ0KYGBgDQoNCkxldCdzIGxvb2sgYXQgdGhlIGRhdGEgaW4gdGhlIGRhdGFiYXNlIGZpcnN0Og0KDQpgYGB7c3FsIGNvbm5lY3Rpb249ZGJ9DQpzZWxlY3QgKiBmcm9tIG5ld01hblR4bnM7DQpgYGANCg0KQW5kLCBmaW5hbGx5LCBsZXQncyBydW4gdGhlIGRhdGUgcXVlcnkgYWdhaW46DQoNCmBgYHtzcWwgY29ubmVjdGlvbj1kYn0NCnNlbGVjdCAqIA0KICBmcm9tIG5ld01hblR4bnMNCiB3aGVyZSB0ZGF0ZSBiZXR3ZWVuICcyMDIyLTAzLTAxJyBhbmQgJzIwMjItMDMtMzEnDQpgYGANCg0KTm93IGl0IHdvcmtlZC4gU28gd2hhdCBkaWQgd2UgbGVhcm4/IERhdGUgY29sdW1ucyBpbiBkYXRhIGZyYW1lcyBkbyBub3QgY29ycmVjdGx5IG1hcCB0byBkYXRlIGNvbHVtbnMgaW4gdGhlIGRhdGFiYXNlLiBJbiBvcmRlciBmb3IgPGNvZGU+ZGJXcml0ZVRhYmxlKCk8L2NvZGU+IHRvIHByb3Blcmx5IHdyaXRlIGRhdGVzIHRvICpkYXRlKiBjb2x1bW5zIGluIHRoZSBkYXRhYmFzZSwgdGhlIGNvbHVtbiBmb3IgdGhlIGRhdGVzIG11c3QgYmUgY2hhcmFjdGVycyBpbiBSOyB0aGV5IGNhbm5vdCBiZSAqRGF0ZSogb2JqZWN0cy4gQ291bnRlcmluaXR1aXRpdmUsIGJ1dCB0aGF0J3MgdGhlIHdheSBpdCB3b3Jrcy4NCg0KIyMgVW5kZXJzdGFuZGluZyBSIHRvIFNRTCBEYXRhIE1hcHBpbmdzDQoNClRvIHVuZGVyc3RhbmQgaG93IFIgbWFwcyBvYmplY3RzIHRvIFNRTCwgd2UgY2FuIHVzZSB0aGUgPGNvZGU+ZGJEYXRhVHlwZSgpPC9jb2RlPiBmdW5jdGlvbi4NCg0KYGBge3J9DQpkYkRhdGFUeXBlKGRiLCBycyR0ZGF0ZSkNCmBgYA0KDQpUaGlzIHRlbGxzIHVzIFIgd2lsbCBjb252ZXJ0IHRoZSBjb2x1bW4gdG8gKlJFQUwqIHdoZW4gd3JpdHRlbiB0byB0aGUgZGF0YWJhc2UsIHdoaWNoIGlzIHdoYXQgd2Ugc2F3IGFib3ZlLg0KDQojIyBDb25jbHVzaW9uDQoNCkRhdGVzIG11c3QgYmUgcHJvcGVybHkgZW5jb2RlZCBmb3IgdGhlbSB0byBiZSBwcm9jZXNzZWQgY29ycmVjdGx5LiBSIGFuZCBTUUwgdXNlIGRhdGVzIGRpZmZlcmVudGx5IGFuZCBjb252ZXJ0aW5nIGJldHdlZW4gdGhlIHR3byBmb3JtYXRzIHJlcXVpcmUgY2FyZS4gRGF0ZSBjb2x1bW5zIGluIGRhdGEgZnJhbWVzIGRvIG5vdCBnZXQgY29udmVydGVkIHByb3Blcmx5IHRvIGNvbHVtbnMgb2YgdHlwZSAqZGF0ZSogaW4gU1FMaXRlLg0KDQojIyBUdXRvcmlhbA0KDQpUaGUgdmlkZW8gdHV0b3JpYWwgZGVtb25zdHJhdGVzIHRoZSBjb25zdHJ1Y3RzIGludHJvZHVjZWQgaW4gdGhpcyBsZXNzb24uDQoNCmBgYHs9aHRtbH0NCjxpZnJhbWUgc3JjPSJodHRwczovL3BsYXllci52aW1lby5jb20vdmlkZW8vNzA0MjYwODM2P2g9NmRiNTM4NjhlZCZhbXA7YmFkZ2U9MCZhbXA7YXV0b3BhdXNlPTAmYW1wO3BsYXllcl9pZD0wJmFtcDthcHBfaWQ9NTg0NzkiIGZyYW1lYm9yZGVyPSIwIiBhbGxvdz0iYXV0b3BsYXk7IGZ1bGxzY3JlZW47IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiB0aXRsZT0iRGF0ZXMgaW4gUiBhbmQgU1FMaXRlIiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4NCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgRmlsZXMgJiBSZXNvdXJjZXMNCg0KYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9DQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgDQogICAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwNCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikNCg0KdGV4dEFMaW5rID0gcGFzdGUwKCJBbGwgRmlsZXMgZm9yIExlc3NvbiAiLCANCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikNCg0KIyBkb3dubG9hZEZpbGVzTGluaygpIGlzIGluY2x1ZGVkIGZyb20gX2luc2VydDJEQi5SDQprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBTZWUgQWxzbw0KDQotICAgWzYuMTEyIEJhc2ljcyBvZiBUZXh0ICYgU3RyaW5nIFByb2Nlc3NpbmcgaW4gUl0oaHR0cDovL2FydGlmaWNpdW0udXMvbGVzc29ucy8wNi5yL2wtNi0xMTItdGV4dC1wcm9jL2wtNi0xMTIuaHRtbCkNCi0gICBbNi4xMDAgQmVnaW5uaW5nIFJdKGh0dHA6Ly9hcnRpZmljaXVtLnVzL2wtNi0xMDAuaHRtbCkNCg0KIyMgRnVydGhlciBTdHVkeQ0KDQotICAgW0RhdGVzIGFuZCBUaW1lcyBpbiBSXShodHRwczovL3d3dy5zdGF0LmJlcmtlbGV5LmVkdS9+czEzMy9kYXRlcy5odG1sKQ0KLSAgIFtEYXRlIEZvcm1hdHMgaW4gUl0oaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vMjAxMy8wOC9kYXRlLWZvcm1hdHMtaW4tci8pDQotICAgW2RiRGF0YVR5cGU6IERldGVybWluZSB0aGUgU1FMIGRhdGEgdHlwZSBvZiBhbiBSIG9iamVjdF0oaHR0cHM6Ly9yZHJyLmlvL2NyYW4vREJJL21hbi9kYkRhdGFUeXBlLmh0bWwpDQoNCiMjIEVycmF0YQ0KDQpOb25lIGNvbGxlY3RlZCB5ZXQuIExldCB1cyBrbm93Lg0KDQpgYGB7PWh0bWx9DQo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tL3N0YXRpYy9mZWVkYmFjazIuanMiIHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQogIG5ldyBKb3Rmb3JtRmVlZGJhY2soew0KICAgIGZvcm1JZDogIjIxMjE4NzA3Mjc4NDE1NyIsDQogICAgYnV0dG9uVGV4dDogIkZlZWRiYWNrIiwNCiAgICBiYXNlOiAiaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLyIsDQogICAgYmFja2dyb3VuZDogIiNGNTkyMDIiLA0KICAgIGZvbnRDb2xvcjogIiNGRkZGRkYiLA0KICAgIGJ1dHRvblNpZGU6ICJsZWZ0IiwNCiAgICBidXR0b25BbGlnbjogImNlbnRlciIsDQogICAgdHlwZTogZmFsc2UsDQogICAgd2lkdGg6IDcwMCwNCiAgICBoZWlnaHQ6IDUwMCwNCiAgICBpc0NhcmRGb3JtOiBmYWxzZQ0KICB9KTsNCjwvc2NyaXB0Pg0KYGBgDQpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9fZGVwbG95S25pdC5SJykpLCBpbmNsdWRlID0gRkFMU0V9DQpgYGANCg==