Package: datasette-dateutil
datasette-dateutildateutil functions for DatasetteInstallationInstall this plugin in the same environment as Datasette.$ datasette install datasette-dateutilUsageThis function adds custom SQL functions that expose functionality from thedateutilPython library.Once installed, the following SQL functions become available:Parsing date stringsdateutil_parse(text)- returns an ISO8601 date string parsed from the text, ornullif the input could not be parsed.dateutil_parse("10 october 2020 3pm")returns2020-10-10T15:00:00.dateutil_parse_fuzzy(text)- same asdateutil_parse()but this also works against strings that contain a date somewhere within them - that date will be returned, ornullif no dates could be found.dateutil_parse_fuzzy("This is due 10 september")returns2020-09-10T00:00:00(but will start returning the 2021 version of that if the year is 2021).Thedateutil_parse()anddateutil_parse_fuzzy()functions both follow the American convention of assuming that1/2/2020lists the month first, evaluating this example to the 2nd of January.If you want to assume that the day comes first, use these two functions instead:dateutil_parse_dayfirst(text)dateutil_parse_fuzzy_dayfirst(text)Here's a query demonstrating these functions:selectdateutil_parse("10 october 2020 3pm"),dateutil_parse_fuzzy("This is due 10 september"),dateutil_parse("1/2/2020"),dateutil_parse("2020-03-04"),dateutil_parse_dayfirst("2020-03-04");Try that queryOptional default datesThedateutil_parse(),dateutil_parse_fuzzy(),dateutil_parse_dayfirst()anddateutil_parse_fuzzy_dayfirst()functions all accept an optional second argument specifying a "default" datetime to consider if some of the details are missing. For example, the following:selectdateutil_parse('1st october','1985-01-01')Will return1985-10-01T00:00:00- the missing year is replaced with the year from the default date.Example query demonstrating the default date argumentCalculating Easterdateutil_easter(year)- returns the date for Easter in that year, for exampledateutil_easter("2020")returns2020-04-12.Example Easter queryJSON arrays of datesSeveral functions return JSON arrays of date strings. These can be used with SQLite'sjson_each()function to perform joins against dates from a specific date range or recurrence rule.These functions can return up to 10,000 results. They will return an error if more than 10,000 dates would be returned - this is to protect against denial of service attacks.dateutil_dates_between('1 january 2020', '5 jan 2020')- given two dates (in any format that can be handled bydateutil_parse()) this function returns a JSON string containing the dates between those two days, inclusive. This example returns["2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05"].dateutil_dates_between('1 january 2020', '5 jan 2020', 0)- set the optional third argument to0to specify that you would like this to be exclusive of the last day. This example returns["2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04"].Try these queriesThedateutil_rrule()anddateutil_rrule_date()functions accept the iCalendar standard ``rrule` format - seethe dateutil documentationfor more examples.This format lets you specify recurrence rules such as "the next four last mondays of the month".dateutil_rrule(rrule, optional_dtsart)- given an rrule returns a JSON array of ISO datetimes. The second argument is optional and will be treated as the start date for the rule.dateutil_rrule_date(rrule, optional_dtsart)- same asdateutil_rrule()but returns ISO dates.Example query:selectdateutil_rrule('FREQ=HOURLY;COUNT=5'),dateutil_rrule_date('FREQ=DAILY;COUNT=3','1st jan 2020');Try the rrule example queryJoining data using json_each()SQLite'sjson_each() functioncan be used to turn a JSON array of dates into a table that can be joined against other data. Here's a query that returns a table showing every day in January 2019:selectvalueasdatefromjson_each(dateutil_dates_between('1 Jan 2019','31 Jan 2019'))Try that queryYou can run joins against this table by assigning it a name using SQLite'ssupport for Common Table Expressions (CTEs).This example query usessubstr(created, 0, 11)to retrieve the date portion of thecreatedcolumn in thefacetable demo table, then joins that against the table of days in January to calculate the count of rows created on each day. TheLEFT JOINagainstdays_in_januaryensures that days which had no created records are still returned in the results, with a count of 0.withcreated_datesas(selectsubstr(created,0,11)asdatefromfacetable),days_in_januaryas(selectvalueasdatefromjson_each(dateutil_dates_between('1 Jan 2019','31 Jan 2019')))selectdays_in_january.date,count(created_dates.date)astotalfromdays_in_januaryleftjoincreated_datesondays_in_january.date=created_dates.dategroupbydays_in_january.date;Try that querywith a bar chart rendered using thedatasette-vegaplugin.DevelopmentTo set up this plugin locally, first checkout the code. Then create a new virtual environment:cd datasette-dateutil
python3 -mvenv venv
source venv/bin/activateOr if you are usingpipenv:pipenv shellNow install the dependencies and tests:pip install -e '.[test]'To run the tests:pytest