-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
this file is useful for finding date,time,year month from timestamp.
- Loading branch information
Showing
1 changed file
with
354 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,354 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
// ---------------------------------------------------------------------------- | ||
// DateTime Library v2.0 | ||
// | ||
// A gas-efficient Solidity date and time library | ||
// | ||
// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary | ||
// | ||
// Tested date range 1970/01/01 to 2345/12/31 | ||
// | ||
// Conventions: | ||
// Unit | Range | Notes | ||
// :-------- |:-------------:|:----- | ||
// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC | ||
// year | 1970 ... 2345 | | ||
// month | 1 ... 12 | | ||
// day | 1 ... 31 | | ||
// hour | 0 ... 23 | | ||
// minute | 0 ... 59 | | ||
// second | 0 ... 59 | | ||
// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday | ||
// | ||
// | ||
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence. | ||
// ---------------------------------------------------------------------------- | ||
|
||
library DateTime { | ||
uint256 constant SECONDS_PER_DAY = 24 * 60 * 60; | ||
uint256 constant SECONDS_PER_HOUR = 60 * 60; | ||
uint256 constant SECONDS_PER_MINUTE = 60; | ||
int256 constant OFFSET19700101 = 2440588; | ||
|
||
uint256 constant DOW_MON = 1; | ||
uint256 constant DOW_TUE = 2; | ||
uint256 constant DOW_WED = 3; | ||
uint256 constant DOW_THU = 4; | ||
uint256 constant DOW_FRI = 5; | ||
uint256 constant DOW_SAT = 6; | ||
uint256 constant DOW_SUN = 7; | ||
|
||
// ------------------------------------------------------------------------ | ||
// Calculate the number of days from 1970/01/01 to year/month/day using | ||
// the date conversion algorithm from | ||
// http://aa.usno.navy.mil/faq/docs/JD_Formula.php | ||
// and subtracting the offset 2440588 so that 1970/01/01 is day 0 | ||
// | ||
// days = day | ||
// - 32075 | ||
// + 1461 * (year + 4800 + (month - 14) / 12) / 4 | ||
// + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 | ||
// - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 | ||
// - offset | ||
// ------------------------------------------------------------------------ | ||
function _daysFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 _days) { | ||
require(year >= 1970); | ||
int256 _year = int256(year); | ||
int256 _month = int256(month); | ||
int256 _day = int256(day); | ||
|
||
int256 __days = _day - 32075 + (1461 * (_year + 4800 + (_month - 14) / 12)) / 4 | ||
+ (367 * (_month - 2 - ((_month - 14) / 12) * 12)) / 12 | ||
- (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) / 4 - OFFSET19700101; | ||
|
||
_days = uint256(__days); | ||
} | ||
|
||
// ------------------------------------------------------------------------ | ||
// Calculate year/month/day from the number of days since 1970/01/01 using | ||
// the date conversion algorithm from | ||
// http://aa.usno.navy.mil/faq/docs/JD_Formula.php | ||
// and adding the offset 2440588 so that 1970/01/01 is day 0 | ||
// | ||
// int L = days + 68569 + offset | ||
// int N = 4 * L / 146097 | ||
// L = L - (146097 * N + 3) / 4 | ||
// year = 4000 * (L + 1) / 1461001 | ||
// L = L - 1461 * year / 4 + 31 | ||
// month = 80 * L / 2447 | ||
// dd = L - 2447 * month / 80 | ||
// L = month / 11 | ||
// month = month + 2 - 12 * L | ||
// year = 100 * (N - 49) + year + L | ||
// ------------------------------------------------------------------------ | ||
function _daysToDate(uint256 _days) internal pure returns (uint256 year, uint256 month, uint256 day) { | ||
unchecked { | ||
int256 __days = int256(_days); | ||
|
||
int256 L = __days + 68569 + OFFSET19700101; | ||
int256 N = (4 * L) / 146097; | ||
L = L - (146097 * N + 3) / 4; | ||
int256 _year = (4000 * (L + 1)) / 1461001; | ||
L = L - (1461 * _year) / 4 + 31; | ||
int256 _month = (80 * L) / 2447; | ||
int256 _day = L - (2447 * _month) / 80; | ||
L = _month / 11; | ||
_month = _month + 2 - 12 * L; | ||
_year = 100 * (N - 49) + _year + L; | ||
|
||
year = uint256(_year); | ||
month = uint256(_month); | ||
day = uint256(_day); | ||
} | ||
} | ||
|
||
function timestampFromDate(uint256 year, uint256 month, uint256 day) internal pure returns (uint256 timestamp) { | ||
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY; | ||
} | ||
|
||
function timestampFromDateTime( | ||
uint256 year, | ||
uint256 month, | ||
uint256 day, | ||
uint256 hour, | ||
uint256 minute, | ||
uint256 second | ||
) | ||
internal | ||
pure | ||
returns (uint256 timestamp) | ||
{ | ||
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR | ||
+ minute * SECONDS_PER_MINUTE + second; | ||
} | ||
|
||
function timestampToDate(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day) { | ||
unchecked { | ||
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
} | ||
} | ||
|
||
function timestampToDateTime(uint256 timestamp) | ||
internal | ||
pure | ||
returns (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) | ||
{ | ||
unchecked { | ||
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
uint256 secs = timestamp % SECONDS_PER_DAY; | ||
hour = secs / SECONDS_PER_HOUR; | ||
secs = secs % SECONDS_PER_HOUR; | ||
minute = secs / SECONDS_PER_MINUTE; | ||
second = secs % SECONDS_PER_MINUTE; | ||
} | ||
} | ||
|
||
function isValidDate(uint256 year, uint256 month, uint256 day) internal pure returns (bool valid) { | ||
if (year >= 1970 && month > 0 && month <= 12) { | ||
uint256 daysInMonth = _getDaysInMonth(year, month); | ||
if (day > 0 && day <= daysInMonth) { | ||
valid = true; | ||
} | ||
} | ||
} | ||
|
||
function isValidDateTime(uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) | ||
internal | ||
pure | ||
returns (bool valid) | ||
{ | ||
if (isValidDate(year, month, day)) { | ||
if (hour < 24 && minute < 60 && second < 60) { | ||
valid = true; | ||
} | ||
} | ||
} | ||
|
||
function isLeapYear(uint256 timestamp) internal pure returns (bool leapYear) { | ||
(uint256 year,,) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
leapYear = _isLeapYear(year); | ||
} | ||
|
||
function _isLeapYear(uint256 year) internal pure returns (bool leapYear) { | ||
leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); | ||
} | ||
|
||
function isWeekDay(uint256 timestamp) internal pure returns (bool weekDay) { | ||
weekDay = getDayOfWeek(timestamp) <= DOW_FRI; | ||
} | ||
|
||
function isWeekEnd(uint256 timestamp) internal pure returns (bool weekEnd) { | ||
weekEnd = getDayOfWeek(timestamp) >= DOW_SAT; | ||
} | ||
|
||
function getDaysInMonth(uint256 timestamp) internal pure returns (uint256 daysInMonth) { | ||
(uint256 year, uint256 month,) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
daysInMonth = _getDaysInMonth(year, month); | ||
} | ||
|
||
function _getDaysInMonth(uint256 year, uint256 month) internal pure returns (uint256 daysInMonth) { | ||
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { | ||
daysInMonth = 31; | ||
} else if (month != 2) { | ||
daysInMonth = 30; | ||
} else { | ||
daysInMonth = _isLeapYear(year) ? 29 : 28; | ||
} | ||
} | ||
|
||
// 1 = Monday, 7 = Sunday | ||
function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) { | ||
uint256 _days = timestamp / SECONDS_PER_DAY; | ||
dayOfWeek = ((_days + 3) % 7) + 1; | ||
} | ||
|
||
function getYear(uint256 timestamp) internal pure returns (uint256 year) { | ||
(year,,) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
} | ||
|
||
function getMonth(uint256 timestamp) internal pure returns (uint256 month) { | ||
(, month,) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
} | ||
|
||
function getDay(uint256 timestamp) internal pure returns (uint256 day) { | ||
(,, day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
} | ||
|
||
function getHour(uint256 timestamp) internal pure returns (uint256 hour) { | ||
uint256 secs = timestamp % SECONDS_PER_DAY; | ||
hour = secs / SECONDS_PER_HOUR; | ||
} | ||
|
||
function getMinute(uint256 timestamp) internal pure returns (uint256 minute) { | ||
uint256 secs = timestamp % SECONDS_PER_HOUR; | ||
minute = secs / SECONDS_PER_MINUTE; | ||
} | ||
|
||
function getSecond(uint256 timestamp) internal pure returns (uint256 second) { | ||
second = timestamp % SECONDS_PER_MINUTE; | ||
} | ||
|
||
function addYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) { | ||
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
year += _years; | ||
uint256 daysInMonth = _getDaysInMonth(year, month); | ||
if (day > daysInMonth) { | ||
day = daysInMonth; | ||
} | ||
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); | ||
require(newTimestamp >= timestamp); | ||
} | ||
|
||
function addMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) { | ||
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
month += _months; | ||
year += (month - 1) / 12; | ||
month = ((month - 1) % 12) + 1; | ||
uint256 daysInMonth = _getDaysInMonth(year, month); | ||
if (day > daysInMonth) { | ||
day = daysInMonth; | ||
} | ||
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); | ||
require(newTimestamp >= timestamp); | ||
} | ||
|
||
function addDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp + _days * SECONDS_PER_DAY; | ||
require(newTimestamp >= timestamp); | ||
} | ||
|
||
function addHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp + _hours * SECONDS_PER_HOUR; | ||
require(newTimestamp >= timestamp); | ||
} | ||
|
||
function addMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE; | ||
require(newTimestamp >= timestamp); | ||
} | ||
|
||
function addSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp + _seconds; | ||
require(newTimestamp >= timestamp); | ||
} | ||
|
||
function subYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) { | ||
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
year -= _years; | ||
uint256 daysInMonth = _getDaysInMonth(year, month); | ||
if (day > daysInMonth) { | ||
day = daysInMonth; | ||
} | ||
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); | ||
require(newTimestamp <= timestamp); | ||
} | ||
|
||
function subMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) { | ||
(uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY); | ||
uint256 yearMonth = year * 12 + (month - 1) - _months; | ||
year = yearMonth / 12; | ||
month = (yearMonth % 12) + 1; | ||
uint256 daysInMonth = _getDaysInMonth(year, month); | ||
if (day > daysInMonth) { | ||
day = daysInMonth; | ||
} | ||
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY); | ||
require(newTimestamp <= timestamp); | ||
} | ||
|
||
function subDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp - _days * SECONDS_PER_DAY; | ||
require(newTimestamp <= timestamp); | ||
} | ||
|
||
function subHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp - _hours * SECONDS_PER_HOUR; | ||
require(newTimestamp <= timestamp); | ||
} | ||
|
||
function subMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE; | ||
require(newTimestamp <= timestamp); | ||
} | ||
|
||
function subSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) { | ||
newTimestamp = timestamp - _seconds; | ||
require(newTimestamp <= timestamp); | ||
} | ||
|
||
function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _years) { | ||
require(fromTimestamp <= toTimestamp); | ||
(uint256 fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); | ||
(uint256 toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY); | ||
_years = toYear - fromYear; | ||
} | ||
|
||
function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _months) { | ||
require(fromTimestamp <= toTimestamp); | ||
(uint256 fromYear, uint256 fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); | ||
(uint256 toYear, uint256 toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY); | ||
_months = toYear * 12 + toMonth - fromYear * 12 - fromMonth; | ||
} | ||
|
||
function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _days) { | ||
require(fromTimestamp <= toTimestamp); | ||
_days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY; | ||
} | ||
|
||
function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _hours) { | ||
require(fromTimestamp <= toTimestamp); | ||
_hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR; | ||
} | ||
|
||
function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _minutes) { | ||
require(fromTimestamp <= toTimestamp); | ||
_minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE; | ||
} | ||
|
||
function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _seconds) { | ||
require(fromTimestamp <= toTimestamp); | ||
_seconds = toTimestamp - fromTimestamp; | ||
} | ||
} |