pragma solidity ^0.6.12; import "./String.sol"; library DateTime { using String for string; struct _DateTime { uint16 year; uint8 month; uint8 day; uint8 hour; uint8 minute; uint8 second; uint8 weekday; } uint256 constant DAY_IN_SECONDS = 86400; uint256 constant YEAR_IN_SECONDS = 31536000; uint256 constant LEAP_YEAR_IN_SECONDS = 31622400; uint256 constant HOUR_IN_SECONDS = 3600; uint256 constant MINUTE_IN_SECONDS = 60; uint16 constant ORIGIN_YEAR = 1970; function isLeapYear(uint16 year) internal pure returns (bool) { if (year % 4 != 0) { return false; } if (year % 100 != 0) { return true; } if (year % 400 != 0) { return false; } return true; } function leapYearsBefore(uint256 year) internal pure returns (uint256) { year -= 1; return year / 4 - year / 100 + year / 400; } function getDaysInMonth(uint8 month, uint16 year) internal pure returns (uint8) { if ( month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ) { return 31; } else if (month == 4 || month == 6 || month == 9 || month == 11) { return 30; } else if (isLeapYear(year)) { return 29; } else { return 28; } } function parseTimestamp(uint256 timestamp) internal pure returns (_DateTime memory dt) { uint256 secondsAccountedFor = 0; uint256 buf; uint8 i; // Year dt.year = getYear(timestamp); buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR); secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf; secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf); // Month uint256 secondsInMonth; for (i = 1; i <= 12; i++) { secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year); if (secondsInMonth + secondsAccountedFor > timestamp) { dt.month = i; break; } secondsAccountedFor += secondsInMonth; } // Day for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) { if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) { dt.day = i; break; } secondsAccountedFor += DAY_IN_SECONDS; } // Hour dt.hour = getHour(timestamp); // Minute dt.minute = getMinute(timestamp); // Second dt.second = getSecond(timestamp); // Day of week. dt.weekday = getWeekday(timestamp); } function getYear(uint256 timestamp) internal pure returns (uint16) { uint256 secondsAccountedFor = 0; uint16 year; uint256 numLeapYears; // Year year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS); numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR); secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears; secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears); while (secondsAccountedFor > timestamp) { if (isLeapYear(uint16(year - 1))) { secondsAccountedFor -= LEAP_YEAR_IN_SECONDS; } else { secondsAccountedFor -= YEAR_IN_SECONDS; } year -= 1; } return year; } function getMonth(uint256 timestamp) internal pure returns (uint8) { return parseTimestamp(timestamp).month; } function getDay(uint256 timestamp) internal pure returns (uint8) { return parseTimestamp(timestamp).day; } function getHour(uint256 timestamp) internal pure returns (uint8) { return uint8((timestamp / 60 / 60) % 24); } function getMinute(uint256 timestamp) internal pure returns (uint8) { return uint8((timestamp / 60) % 60); } function getSecond(uint256 timestamp) internal pure returns (uint8) { return uint8(timestamp % 60); } function getWeekday(uint256 timestamp) internal pure returns (uint8) { return uint8((timestamp / DAY_IN_SECONDS + 4) % 7); } function convertTimestampToDateTime(uint256 _timestamp) internal pure returns (string memory) { string memory prefix = "0"; string memory year = ToString(getYear(_timestamp)); string memory month = getMonth(_timestamp) < 10 ? prefix.append(ToString(getMonth(_timestamp))) : ToString(getMonth(_timestamp)); string memory day = getDay(_timestamp) < 10 ? prefix.append(ToString(getDay(_timestamp))) : ToString(getDay(_timestamp)); string memory hour = getHour(_timestamp) < 10 ? prefix.append(ToString(getHour(_timestamp))) : ToString(getHour(_timestamp)); string memory minute = getMinute(_timestamp) < 10 ? prefix.append(ToString(getMinute(_timestamp))) : ToString(getMinute(_timestamp)); string memory second = getSecond(_timestamp) < 10 ? prefix.append(ToString(getSecond(_timestamp))) : ToString(getSecond(_timestamp)); string memory date = year.append("-").append(month).append("-").append( day ); string memory time = hour.append(":").append(minute).append(":").append( second ); return date.append("T").append(time); } function ToString(uint16 _i) internal pure returns (string memory) { if (_i == 0) { return "0"; } uint256 j = _i; uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint256 k = len; while (_i != 0) { k = k - 1; uint8 temp = (48 + uint8(_i - (_i / 10) * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; _i /= 10; } return string(bstr); } }