Gas-Efficient Solidity DateTime Library
This is experimental software and is provided on an "as is" and "as available" basis.
We do not give any warranties and will not be liable for any loss incurred through any use of this codebase.
To install with Foundry:
forge install Atarpara/DateTimeLibTo install with Hardhat or Truffle:
npm install All dates, times and Unix timestamps are UTC.
| Unit | Range | Notes |
|---|---|---|
| timestamp | 0..0x1e18549868c76ff | Unix timestamp. |
| epochDay | 0..0x16d3e098039 | Days since 1970-01-01. |
| year | 1970..0xffffffff | Gregorian calendar year. |
| month | 1..12 | Gregorian calendar month. |
| day | 1..31 | Gregorian calendar day of month. |
| weekday | 1..7 | The day of the week (1-indexed). |
All functions operate on the uint256 timestamp data type.
Calculate the number of days days from 1970/01/01 to year/month/day.
function dateToEpochDay(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 epochDay)NOTE This function does not validate the year/month/day input. Use isSupportedDate(..) to validate the input if necessary.
Example:
if(DateTimeLib.isSupportedDate(1970,2,1))
uint256 day = DateTimeLib.dateToEpochDay(1970,2,1) // returns 31 day
if(DateTimeLib.isSupportedDate(1971,1,1))
uint256 day = DateTimeLib.dateToEpochDay(1971,1,1) // returns 365 dayCalculate year/month/day from the number of days days since 1970/01/01 .
function epochDayToDate(uint256 epochDay) internal pure returns (uint256 year, uint256 month, uint256 day)NOTE This function does not validate the epochDay input. Use isSupportedEpochDay(..) to validate the input if necessary.
Example:
if(DateTimeLib.isSupportedEpochDay(0))
(uint256 year, uint256 month, uint256 day) = DateTimeLib.dateToEpochDay(0) // 1970-01-01
if(DateTimeLib.isSupportedEpochDay(224))
(uint256 year, uint256 month, uint256 day) = DateTimeLib.dateToEpochDay(224) // 1970-08-13Calculate the timestamp from year/month/day.
function dateToTimestamp(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 result)NOTE This function does not validate the year/month/day input. Use isSupportedDate(...) to validate the input if necessary.
Example:
if(DateTimeLib.isSupportedDate(1970,2,1))
uint256 timestamp = DateTimeLib.dateToTimestamp(1970,2,1) // returns 2658600
if(DateTimeLib.isSupportedDate(2022,11,10))
uint256 timestamp = DateTimeLib.dateToTimestamp(2022,11,10) // returns 1668018600Calculate year/month/day from timestamp.
function timestampToDate(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day)NOTE This function does not validate the timestamp input. Use isSupportedTimestamp(...) to validate the input if necessary.
Example:
if(DateTimeLib.isSupportedTimestamp(2658650))
(uint256 year, uint256 month, uint256 day) = DateTimeLib.timestampToDate(2658600) // returns 1970-02-01
if(DateTimeLib.isSupportedTimestamp(1668018900))
(uint256 year, uint256 month, uint256 day) = DateTimeLib.timestampToDate(1668018900) // returns 2022-11-10Calculate timestamp from year/month/day/hour/minute/second.
function dateTimeToTimestamp(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) internal pure returns (uint256 result)NOTE This function does not validate the year/month/day/hour/minute/second input. Use isSupportedDateTime(...) to validate the input if necessary.
Example:
if(DateTimeLib.isSupportedDateTime(1970,02,01,23,30,59))
uint256 timestamp = DateTimeLib.dateTimeToTimestamp(1970,02,01,23,30,59) // returns 2763059
if(DateTimeLib.isSupportedDateTime(2022,11,10,06,47,30))
uint256 timestamp = DateTimeLib.dateTimeToTimestamp(2022,11,10,12,17,30) // returns 1668062850Calculate year/month/day/hour/minute/second from timestamp.
function timestampToDateTime(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second)NOTE This function does not validate the year/month/day/hour/minute/second input. Use isSupportedTimestamp(...) to validate the input if necessary.
Example:
if(DateTimeLib.isSupportedTimestamp(2763059))
(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) = DateTimeLib.timestampToDateTime(2763059) // returns 1970-02-01 23:30:59
if(DateTimeLib.isSupportedTimestamp(1668062850))
(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) = DateTimeLib.timestampToDateTime(1668062850) // returns 2022-11-10 12:17:30Check given year is leap or not.
function isLeapYear(uint256 year) internal pure returns (bool leap) Example:
bool isLeap = DateTimeLib.isLeapYear(1900) // returns False
bool isLeap = DateTimeLib.isLeapYear(2004) // returns True
bool isLeap = DateTimeLib.isLeapYear(2400) // returns TrueReturn number of day in the month daysInMonth for the month specified by year/month.
function daysInMonth(uint256 year, uint256 month) internal pure returns (uint256 result)Example:
uint256 day = DateTimeLib.daysInMonth(01, 1900) // returns 31
uint256 day = DateTimeLib.daysInMonth(02, 2001) // returns 28
uint256 day = DateTimeLib.daysInMonth(02, 2004) // returns 29Return the day of the week weekday (1 = Monday,2 = Tuesday ..., 7 = Sunday) for the date specified by timestamp.
function weekday(uint256 timestamp) internal pure returns (uint256 result)Check the given date is valid or not.
function isSupportedDate(uint256 year, uint256 month, uint256 day) internal pure returns (bool result)NOTE This algorithm supported fully uint256 limit but Restricted max supported year to type(uint32).max. By the time, we will already be either extinct, an interstellar species, or the Earth's motion would have drastically changed. A smaller supported range will mean smaller bytecode needed to validate the dates.
Check the given datetime is valid or not.
function function isSupportedDateTime(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) internal pure returns (bool result)Check the given epoch day is valid or not.
function isSupportedEpochDay(uint256 epochDay) internal pure returns (bool result)NOTE This algorithm supported fully uint256 limit but Restricted max supported epochDay to MAX_SUPPORTED_EPOCH_DAY. By the time, we will already be either extinct, an interstellar species, or the Earth's motion would have drastically changed.
Check the given timestamp is valid or not.
function isSupportedTimestamp(uint256 timestamp) internal pure returns (bool result)NOTE This algorithm supported fully uint256 limit but Restricted max supported timstamp to MAX_SUPPORTED_TIMESTAMP.
Return timestamp of the Nth weekday from the year/month.
function nthWeekdayInMonthOfYearTimestamp(uint256 year, uint256 month, uint256 n, uint256 wd) internal pure returns (uint256 result)NOTE This function does not validate the year/month and wd input. Use isSupportedDate(year,month,1) to validate for year/month and wd must be in range of [1,7].
Example:
uint256 timestamp = DateTimeLib.nthWeekdayInMonthOfYearTimestamp(2022,12,1,DateTimeLib.FRI) // returns 1669939200 (1st Friday December 2022)
uint256 timestamp = DateTimeLib.nthWeekdayInMonthOfYearTimestamp(2022,11,6,DateTimeLib.WED) // returns 0 (6th Wednesday November 2022)Calculate timestamp of the most recent Monday.
function mondayTimestamp(uint256 timestamp) internal pure returns (uint256 result)NOTE If timestamp < 345600 it returns 0 as per UTC it is thursday.
Calculate timestamp falls on a Saturday or Sunday
function isWeekEnd(uint256 timestamp) internal pure returns (bool result)Add numYears years to the date and time specified by timestamp.
Note that the resulting day of the month will be adjusted if it exceeds the valid number of days in the month. For example, if the original date is 2020/02/29 and an additional year is added to this date, the resulting date will be an invalid date of 2021/02/29. The resulting date is then adjusted to 2021/02/28.
function addYears(uint256 timestamp, uint256 numYears) internal pure returns (uint256 result)Add numMonths months to the date and time specified by timestamp.
Note that the resulting day of the month will be adjusted if it exceeds the valid number of days in the month. For example, if the original date is 2019/01/31 and an additional month is added to this date, the resulting date will be an invalid date of 2019/02/31. The resulting date is then adjusted to 2019/02/28.
function addMonths(uint256 timestamp, uint256 numMonths) internal pure returns (uint256 result)Add numDays days to the date and time specified by timestamp.
function addDays(uint256 timestamp, uint256 numDays) internal pure returns (uint256 result)Add numHours hours to the date and time specified by timestamp.
function addHours(uint256 timestamp, uint256 numHours) internal pure returns (uint256 result)Add numMinutes minutes to the date and time specified by timestamp.
function addMinutes(uint256 timestamp, uint256 numMinutes) internal pure returns (uint256 result)Add numSeconds seconds to the date and time specified by timestamp.
function addSeconds(uint256 timestamp, uint256 numSeconds) internal pure returns (uint256 result)Subtracts numYears years from the unix timestamp.
Note that the resulting day of the month will be adjusted if it exceeds the valid number of days in the month. For example, if the original date is 2020/02/29 and a year is subtracted from this date, the resulting date will be an invalid date of 2019/02/29. The resulting date is then adjusted to 2019/02/28.
function subYears(uint256 timestamp, uint256 numYears) internal pure returns (uint256 result)Subtracts numMonths months from the unix timestamp.
Note that the resulting day of the month will be adjusted if it exceeds the valid number of days in the month. For example, if the original date is 2019/03/31 and a month is subtracted from this date, the resulting date will be an invalid date of 2019/02/31. The resulting date is then adjusted to 2019/02/28.
function subMonths(uint256 timestamp, uint256 numMonths) internal pure returns (uint256 result)Subtracts numDays days from the unix timestamp.
function subDays(uint256 timestamp, uint256 numDays) internal pure returns (uint256 result)Subtracts numHours from the unix timestamp.
function subHours(uint256 timestamp, uint256 numHours) internal pure returns (uint256 result)Subtracts numMinutes from the unix timestamp.
function subMinutes(uint256 timestamp, uint256 numMinutes) internal pure returns (uint256 result)Subtracts numSeconds from the unix timestamp.
function subSeconds(uint256 timestamp, uint256 numSeconds) internal pure returns (uint256 result)Calculate the number of years between the dates specified by fromTimeStamp and toTimestamp.
Note that Even if the true time difference is less than a year, the difference can be non-zero is the timestamps are from diffrent Gregorian calendar years.
function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result)Calculate the number of months between the dates specified by fromTimeStamp and toTimestamp.
Note that Even if the true time difference is less than a month, the difference can be non-zero is the timestamps are from diffrent Gregorian calendar months.
function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result)Calculate the number of days between the dates specified by fromTimeStamp and toTimestamp.
function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result)Calculate the number of hours between the dates specified by fromTimeStamp and toTimestamp.
function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result)Calculate the number of minutes between the dates specified by fromTimeStamp and toTimestamp.
function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result)Calculate the number of seconds between the dates specified by fromTimeStamp and toTimestamp.
function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 result)This repository is inspired by or directly modified from many sources, primarily:
A copy of the webpage with the algorithm Date Time Algorithm.