BokkyPooBah’s Gas-Efficient Solidity DateTime Library
Time is represented in Solidity smart contracts as a timestamp, the number of seconds since 1970/01/01 00:00:00 UTC. This is the same unit as the Unix timestamp. There are currently no functions available to convert from this timestamp into the calendar year/month/day and the time of day hour:minute:second.
BokkyPooBah’s Gas-Efficient Solidity DateTime Library aims to provide the additional functions required to convert from the timestamp into year/month/day hour:minute:second, and back.
In summary, the functions in this library provides the following features :
- Convert from timestamp to year/month/day, and back
- Convert from timestamp to year/month/day hour:minute:second, and back
- Determine if a timestamp represents a leap year, a week end or a week day
- Compute the day of the week for a timestamp
- Add years, months, days, hours, minutes or seconds to a timestamp
- Subtract years, months, days, hours, minutes or seconds from a timestamp
- Compute the difference between two timestamps in years, months, days, hours, minutes or seconds
This library has been designed for easy inclusion into your smart contracts — the functions are declared internal
so they will be compiled inline into your smart contracts for simpler deployments.
The source code for the library is available at BokkyPooBahsDateTimeLibrary.sol .
Sample usage in smart contracts can be found in BokkyPooBahsDateTimeContract.sol and TestDateTime.sol . These have been deployed to the Ropsten testnet at 0x947cc35992e6723de50bf704828a01fd2d5d6641 and 0xa068fe3e029a972ecdda2686318806d2b19875d1 , and on Mainnet at 0x23d23d8f243e57d0b924bff3a3191078af325101 and 0x78f96b2d5f717fa9ad416957b79d825cc4cce69d . Click on the links and select the Read Contract tab to test out the date/time/timestamp functions.
See Conventions for the conventions used in this library. See Functions for the list of functions available in this library.See Questions And Answers for common questions.
And how gas-efficient is this library?
From Gas Cost, timestampToDateTime(…)
has an execution gas cost of 3,101 gas, and timestampFromDateTime(…)
has an execution gas cost of 2,566 gas. You can compare these numbers against the low level EVM opcode gas cost.
Below is my recent re-test with Remix compiling with Solidity 0.4.24.
timestampToDateTime(uint timestamp)
used 1,945 gas:
timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second)
used 1,077 gas:
So what can this library be used for?
- Recurring subscriptions on the blockchain, payable on a particular day in the month ERC-948/EIP-1337
- Smart contracts making periodic payments, e.g., bonds or equities, where the payments are made quarterly or semiannually
- Smart contracts that release payments periodically, e.g., release x ETH every birthday
- Smart contracts generating periodic calendar events
- And any new use case made possible by this library
The Original Date Conversion Algorithms
The original date conversion algorithms are sourced from Converting Between Julian Dates and Gregorian Calendar Dates, designed by Fliegel and van Flandern (1968).
The following Fortran algorithm is used to convert a Gregorian date (year/month/day) into a Julian date (number of days relative to a reference point):
And the following Fortran algorithm is used to convert a Julian date into a Gregorian date (year/month/day):
The Gas-Efficient Solidity Date Conversion Algorithms
BokkyPooBah’s Gas-Efficient Solidity DateTime library uses a similar algorithm to convert between a Unix timestamp (number of seconds since 1970/01/01 00:00:00 UTC) and a DateTime (year/month/day hour:minute:second).
The following algorithm is used to convert year/month/day into the number of days since 1970/01/01:
And the following algorithm is used to convert from the number of days since 1970/01/01 into year/month/day:
The Gas-Efficient Solidity DateTime Conversion Algorithms
The date conversion algorithms above are used to translated between the number of days since 1970/01/01 and year/month/day.
As the Unix timestamp represents the number of seconds since 1970/01/01 00:00:00 UTC, the number of days since 1970/01/01 is multiplied by the number of seconds in each day (60 * 60 * 24) and representing the hour/minute/seconds by the number of seconds they represent.
Thank Yous!
I would like to thank Alex Kampa, James Zaki and Adrian Guerrera for assisting in the testing and audit of this DateTime library. Thanks also to Oleksii Matiiasevych for asking about leap seconds.
And If You Find This DateTime Library Useful
If you find this library useful for your project, especially commercial projects, please donate to 0xb6dAC2C5A0222f6794265249ACE15568B750c2d1. I hope to cover my cost of getting this library independently audited.
Enjoy!
BokkyPooBah / Bok Consulting Pty Ltd — Sep 2 2018.