├── requirements-dev.txt ├── .gitignore ├── tests └── datetime │ ├── test_to_timestamp.py │ ├── test_weekday.py │ ├── test_isLeapYear.py │ ├── test_hour.py │ ├── test_month.py │ ├── test_day.py │ ├── test_second.py │ ├── test_minute.py │ └── test_year.py ├── LICENSE ├── contracts ├── api.sol └── DateTime.sol └── README.md /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | pytz==2015.6 2 | populus==0.5.1 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .password 2 | .genesis.json 3 | build/ 4 | dist/ 5 | chains/ 6 | **/_build 7 | -------------------------------------------------------------------------------- /tests/datetime/test_to_timestamp.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import datetime 4 | 5 | 6 | @pytest.mark.parametrize( 7 | 'dt,timestamp', 8 | ( 9 | (datetime.datetime(1970, 1, 1), 0), 10 | (datetime.datetime(1970, 12, 31, 23, 59, 59), 31535999), 11 | (datetime.datetime(1971, 1, 1), 31536000), 12 | (datetime.datetime(2016, 2, 29, 23, 59, 59), 1456790399), 13 | (datetime.datetime(2016, 3, 1), 1456790400), 14 | ), 15 | ) 16 | def test_dt_to_timestamp(deployed_contracts, dt, timestamp): 17 | crontab = deployed_contracts.DateTime 18 | assert crontab.toTimestamp(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) == timestamp 19 | -------------------------------------------------------------------------------- /tests/datetime/test_weekday.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | @pytest.mark.parametrize( 4 | 'timestamp,weekday', 5 | ( 6 | (67737599, 3), 7 | (67737600, 4), 8 | (67823999, 4), 9 | (67824000, 5), 10 | (67910399, 5), 11 | (67910400, 6), 12 | (67996799, 6), 13 | (67996800, 0), 14 | (68083199, 0), 15 | (68083200, 1), 16 | (68169599, 1), 17 | (68169600, 2), 18 | (68255999, 2), 19 | (68256000, 3), 20 | (68342399, 3), 21 | (68342400, 4), 22 | ), 23 | ) 24 | def test_get_weekday_from_timestamp(deployed_contracts, timestamp, weekday): 25 | crontab = deployed_contracts.DateTime 26 | assert crontab.getWeekday(timestamp) == weekday 27 | 28 | -------------------------------------------------------------------------------- /tests/datetime/test_isLeapYear.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | LEAP_YEARS = { 4 | 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 5 | 2020, 2024, 2028, 2032, 2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 6 | 2072, 2076, 2080, 2084, 2088, 2092, 2096, 2104, 2108, 2112, 2116, 2120, 2124, 7 | 2128, 2132, 2136, 2140, 2144, 2148, 2152, 2156, 2160, 2164, 2168, 2172, 2176, 8 | 2180, 2184, 2188, 2192, 2196, 2204, 2208, 2212, 2216, 2220, 2224, 2228, 2232, 9 | 2236, 2240, 2244, 2248, 2252, 2256, 2260, 2264, 2268, 2272, 2276, 2280, 2284, 10 | 2288, 2292, 2296, 2304, 2308, 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2340, 11 | 2344, 2348, 2352, 2356, 2360, 2364, 2368, 2372, 2376, 2380, 2384, 2388, 2392, 12 | 2396, 2400, 13 | } 14 | 15 | 16 | @pytest.mark.parametrize( 17 | 'year', range(1970, 2401), 18 | ) 19 | def test_is_leap_year(deployed_contracts, year): 20 | crontab = deployed_contracts.DateTime 21 | if year in LEAP_YEARS: 22 | assert crontab.isLeapYear(year) is True 23 | else: 24 | assert crontab.isLeapYear(year) is False 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Piper Merriam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /contracts/api.sol: -------------------------------------------------------------------------------- 1 | contract DateTimeAPI { 2 | /* 3 | * Abstract contract for interfacing with the DateTime contract. 4 | * 5 | */ 6 | function isLeapYear(uint16 year) constant returns (bool); 7 | function getYear(uint timestamp) constant returns (uint16); 8 | function getMonth(uint timestamp) constant returns (uint8); 9 | function getDay(uint timestamp) constant returns (uint8); 10 | function getHour(uint timestamp) constant returns (uint8); 11 | function getMinute(uint timestamp) constant returns (uint8); 12 | function getSecond(uint timestamp) constant returns (uint8); 13 | function getWeekday(uint timestamp) constant returns (uint8); 14 | function toTimestamp(uint16 year, uint8 month, uint8 day) constant returns (uint timestamp); 15 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) constant returns (uint timestamp); 16 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) constant returns (uint timestamp); 17 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) constant returns (uint timestamp); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /tests/datetime/test_hour.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | @pytest.mark.parametrize( 4 | 'timestamp,hour', 5 | ( 6 | (63071999, 23), 7 | (63072000, 0), 8 | (63075599, 0), 9 | (63075600, 1), 10 | (63079199, 1), 11 | (63079200, 2), 12 | (63082799, 2), 13 | (63082800, 3), 14 | (63086399, 3), 15 | (63086400, 4), 16 | (63089999, 4), 17 | (63090000, 5), 18 | (63093599, 5), 19 | (63093600, 6), 20 | (63097199, 6), 21 | (63097200, 7), 22 | (63100799, 7), 23 | (63100800, 8), 24 | (63104399, 8), 25 | (63104400, 9), 26 | (63107999, 9), 27 | (63108000, 10), 28 | (63111599, 10), 29 | (63111600, 11), 30 | (63115199, 11), 31 | (63115200, 12), 32 | (63118799, 12), 33 | (63118800, 13), 34 | (63122399, 13), 35 | (63122400, 14), 36 | (63125999, 14), 37 | (63126000, 15), 38 | (63129599, 15), 39 | (63129600, 16), 40 | (63133199, 16), 41 | (63133200, 17), 42 | (63136799, 17), 43 | (63136800, 18), 44 | (63140399, 18), 45 | (63140400, 19), 46 | (63143999, 19), 47 | (63144000, 20), 48 | (63147599, 20), 49 | (63147600, 21), 50 | (63151199, 21), 51 | (63151200, 22), 52 | (63154799, 22), 53 | (63154800, 23), 54 | (63158400, 0), 55 | ), 56 | ) 57 | def test_get_hour_from_timestamp(deployed_contracts, timestamp, hour): 58 | crontab = deployed_contracts.DateTime 59 | assert crontab.getHour(timestamp) == hour 60 | -------------------------------------------------------------------------------- /tests/datetime/test_month.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | 5 | @pytest.mark.parametrize( 6 | 'timestamp,month', 7 | ( 8 | # Non leap year. 9 | (0, 1), 10 | (2678399, 1), 11 | (2678400, 2), 12 | (5097599, 2), 13 | (5097600, 3), 14 | (7775999, 3), 15 | (7776000, 4), 16 | (10367999, 4), 17 | (10368000, 5), 18 | (13046399, 5), 19 | (13046400, 6), 20 | (15638399, 6), 21 | (15638400, 7), 22 | (18316799, 7), 23 | (18316800, 8), 24 | (20995199, 8), 25 | (20995200, 9), 26 | (23587199, 9), 27 | (23587200, 10), 28 | (26265599, 10), 29 | (26265600, 11), 30 | (28857599, 11), 31 | (28857600, 12), 32 | (31535999, 12), 33 | (31536000, 1), 34 | 35 | # Leap Year 36 | (63071999, 12), 37 | (63072000, 1), 38 | (65750399, 1), 39 | (65750400, 2), 40 | (68255999, 2), 41 | (68256000, 3), 42 | (70934399, 3), 43 | (70934400, 4), 44 | (73526399, 4), 45 | (73526400, 5), 46 | (76204799, 5), 47 | (76204800, 6), 48 | (78796799, 6), 49 | (78796800, 7), 50 | (81475199, 7), 51 | (81475200, 8), 52 | (84153599, 8), 53 | (84153600, 9), 54 | (86745599, 9), 55 | (86745600, 10), 56 | (89423999, 10), 57 | (89424000, 11), 58 | (92015999, 11), 59 | (92016000, 12), 60 | (94694399, 12), 61 | (94694400, 1), 62 | ), 63 | ) 64 | def test_get_month_from_timestamp(deployed_contracts, timestamp, month): 65 | crontab = deployed_contracts.DateTime 66 | assert crontab.getMonth(timestamp) == month 67 | 68 | -------------------------------------------------------------------------------- /tests/datetime/test_day.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | @pytest.mark.parametrize( 4 | 'timestamp,day', 5 | ( 6 | # Non leap year. 7 | (0, 1), 8 | (2678399, 31), 9 | (2678400, 1), 10 | (5097599, 28), 11 | (5097600, 1), 12 | (7775999, 31), 13 | (7776000, 1), 14 | (10367999, 30), 15 | (10368000, 1), 16 | (13046399, 31), 17 | (13046400, 1), 18 | (15638399, 30), 19 | (15638400, 1), 20 | (18316799, 31), 21 | (18316800, 1), 22 | (20995199, 31), 23 | (20995200, 1), 24 | (23587199, 30), 25 | (23587200, 1), 26 | (26265599, 31), 27 | (26265600, 1), 28 | (28857599, 30), 29 | (28857600, 1), 30 | (31535999, 31), 31 | (31536000, 1), 32 | 33 | # Leap Year 34 | (63071999, 31), # Dec 31 1971 35 | (63072000, 1), # Jan 1 1972 36 | (65750399, 31), 37 | (65750400, 1), # Feb 1 1972 38 | (68255999, 29), 39 | (68256000, 1), # Mar 1 1972 40 | (70934399, 31), 41 | (70934400, 1), # Apr 1 1972 42 | (73526399, 30), 43 | (73526400, 1), # May 1 1972 44 | (76204799, 31), 45 | (76204800, 1), # Jun 1 1972 46 | (78796799, 30), 47 | (78796800, 1), # Jul 1 1972 48 | (81475199, 31), 49 | (81475200, 1), # Aug 1 1972 50 | (84153599, 31), 51 | (84153600, 1), # Sep 1 1972 52 | (86745599, 30), 53 | (86745600, 1), # Oct 1 1972 54 | (89423999, 31), 55 | (89424000, 1), # Nov 1 1972 56 | (92015999, 30), 57 | (92016000, 1), # Dec 1 1972 58 | (94694399, 31), 59 | (94694400, 1), # Jan 1 1972 60 | ), 61 | ) 62 | def test_get_day_from_timestamp(deployed_contracts, timestamp, day): 63 | crontab = deployed_contracts.DateTime 64 | assert crontab.getDay(timestamp) == day 65 | -------------------------------------------------------------------------------- /tests/datetime/test_second.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | @pytest.mark.parametrize( 4 | 'timestamp,second', 5 | ( 6 | (63071999, 59), 7 | (63072000, 0), 8 | (63072001, 1), 9 | (63072002, 2), 10 | (63072003, 3), 11 | (63072004, 4), 12 | (63072005, 5), 13 | (63072006, 6), 14 | (63072007, 7), 15 | (63072008, 8), 16 | (63072009, 9), 17 | (63072010, 10), 18 | (63072011, 11), 19 | (63072012, 12), 20 | (63072013, 13), 21 | (63072014, 14), 22 | (63072015, 15), 23 | (63072016, 16), 24 | (63072017, 17), 25 | (63072018, 18), 26 | (63072019, 19), 27 | (63072020, 20), 28 | (63072021, 21), 29 | (63072022, 22), 30 | (63072023, 23), 31 | (63072024, 24), 32 | (63072025, 25), 33 | (63072026, 26), 34 | (63072027, 27), 35 | (63072028, 28), 36 | (63072029, 29), 37 | (63072030, 30), 38 | (63072031, 31), 39 | (63072032, 32), 40 | (63072033, 33), 41 | (63072034, 34), 42 | (63072035, 35), 43 | (63072036, 36), 44 | (63072037, 37), 45 | (63072038, 38), 46 | (63072039, 39), 47 | (63072040, 40), 48 | (63072041, 41), 49 | (63072042, 42), 50 | (63072043, 43), 51 | (63072044, 44), 52 | (63072045, 45), 53 | (63072046, 46), 54 | (63072047, 47), 55 | (63072048, 48), 56 | (63072049, 49), 57 | (63072050, 50), 58 | (63072051, 51), 59 | (63072052, 52), 60 | (63072053, 53), 61 | (63072054, 54), 62 | (63072055, 55), 63 | (63072056, 56), 64 | (63072057, 57), 65 | (63072058, 58), 66 | (63072059, 59), 67 | (63072060, 0), 68 | ), 69 | ) 70 | def test_get_second_from_timestamp(deployed_contracts, timestamp, second): 71 | crontab = deployed_contracts.DateTime 72 | assert crontab.getSecond(timestamp) == second 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Ethereum Date and Time tools 2 | 3 | Contract which implements utilities for working with datetime values in 4 | ethereum. 5 | 6 | Contract Deployments: 7 | 8 | - Mainnet: [`0x1a6184CD4C5Bea62B0116de7962EE7315B7bcBce`](https://etherscan.io/address/0x1a6184cd4c5bea62b0116de7962ee7315b7bcbce) 9 | - Rinkeby: [`0x92482Ba45A4D2186DafB486b322C6d0B88410FE7`](https://rinkeby.etherscan.io/address/0x92482ba45a4d2186dafb486b322c6d0b88410fe7) 10 | 11 | 12 | To verify, you need to compare the code on the blockchain with the runtime code 13 | which can be gotten from ``solc contracts/DateTime.sol --optimize --bin-runtime``. 14 | 15 | Also you can find it already verified at https://etherscan.io/address/0x1a6184cd4c5bea62b0116de7962ee7315b7bcbce#code 16 | 17 | ### DateTime struct 18 | 19 | Internally, the following **struct** is used to represent date-time object. 20 | 21 | ``` 22 | struct DateTime { 23 | uint16 year; 24 | uint8 month; 25 | uint8 day; 26 | uint8 hour; 27 | uint8 minute; 28 | uint8 second; 29 | uint8 weekday; 30 | } 31 | ``` 32 | 33 | 34 | ### API 35 | 36 | * `isLeapYear(uint16 year) constant returns (bool)` 37 | 38 | Given an integer year value, returns whether it is a leap year. 39 | 40 | 41 | * `parseTimestamp(uint timestamp) internal returns (DateTime dt)` 42 | 43 | Given a unix timestamp, returns the `DateTime` representation of it. 44 | 45 | 46 | * `getYear(uint timestamp) constant returns (uint16)` 47 | 48 | Given a unix timestamp, returns the `DateTime.year` value for the timestamp. 49 | 50 | 51 | * `getMonth(uint timestamp) constant returns (uint16)` 52 | 53 | Given a unix timestamp, returns the `DateTime.month` value for the timestamp. 54 | 55 | 56 | * `getDay(uint timestamp) constant returns (uint16)` 57 | 58 | Given a unix timestamp, returns the `DateTime.day` value for the timestamp. 59 | 60 | 61 | * `getHour(uint timestamp) constant returns (uint16)` 62 | 63 | Given a unix timestamp, returns the `DateTime.hour` value for the timestamp. 64 | 65 | 66 | * `getMinute(uint timestamp) constant returns (uint16)` 67 | 68 | Given a unix timestamp, returns the `DateTime.minute` value for the timestamp. 69 | 70 | 71 | * `getSecond(uint timestamp) constant returns (uint16)` 72 | 73 | Given a unix timestamp, returns the `DateTime.second` value for the timestamp. 74 | 75 | 76 | * `getWeekday(uint timestamp) constant returns (uint8)` 77 | 78 | Given a unix timestamp, returns the `DateTime.weekday` value for the timestamp. 79 | 80 | 81 | * `toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) constant returns (uint timestamp)` 82 | * `toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) constant returns (uint timestamp)` 83 | * `toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) constant returns (uint timestamp)` 84 | * `toTimestamp(uint16 year, uint8 month, uint8 day) constant returns (uint timestamp)` 85 | 86 | Returns the unix timestamp representation for the given date and time values. 87 | -------------------------------------------------------------------------------- /tests/datetime/test_minute.py: -------------------------------------------------------------------------------- 1 | 2 | import pytest 3 | 4 | @pytest.mark.parametrize( 5 | 'timestamp,minute', 6 | ( 7 | (63071999, 59), 8 | (63072000, 0), 9 | (63072059, 0), 10 | (63072060, 1), 11 | (63072119, 1), 12 | (63072120, 2), 13 | (63072179, 2), 14 | (63072180, 3), 15 | (63072239, 3), 16 | (63072240, 4), 17 | (63072299, 4), 18 | (63072300, 5), 19 | (63072359, 5), 20 | (63072360, 6), 21 | (63072419, 6), 22 | (63072420, 7), 23 | (63072479, 7), 24 | (63072480, 8), 25 | (63072539, 8), 26 | (63072540, 9), 27 | (63072599, 9), 28 | (63072600, 10), 29 | (63072659, 10), 30 | (63072660, 11), 31 | (63072719, 11), 32 | (63072720, 12), 33 | (63072779, 12), 34 | (63072780, 13), 35 | (63072839, 13), 36 | (63072840, 14), 37 | (63072899, 14), 38 | (63072900, 15), 39 | (63072959, 15), 40 | (63072960, 16), 41 | (63073019, 16), 42 | (63073020, 17), 43 | (63073079, 17), 44 | (63073080, 18), 45 | (63073139, 18), 46 | (63073140, 19), 47 | (63073199, 19), 48 | (63073200, 20), 49 | (63073259, 20), 50 | (63073260, 21), 51 | (63073319, 21), 52 | (63073320, 22), 53 | (63073379, 22), 54 | (63073380, 23), 55 | (63073439, 23), 56 | (63073440, 24), 57 | (63073499, 24), 58 | (63073500, 25), 59 | (63073559, 25), 60 | (63073560, 26), 61 | (63073619, 26), 62 | (63073620, 27), 63 | (63073679, 27), 64 | (63073680, 28), 65 | (63073739, 28), 66 | (63073740, 29), 67 | (63073799, 29), 68 | (63073800, 30), 69 | (63073859, 30), 70 | (63073860, 31), 71 | (63073919, 31), 72 | (63073920, 32), 73 | (63073979, 32), 74 | (63073980, 33), 75 | (63074039, 33), 76 | (63074040, 34), 77 | (63074099, 34), 78 | (63074100, 35), 79 | (63074159, 35), 80 | (63074160, 36), 81 | (63074219, 36), 82 | (63074220, 37), 83 | (63074279, 37), 84 | (63074280, 38), 85 | (63074339, 38), 86 | (63074340, 39), 87 | (63074399, 39), 88 | (63074400, 40), 89 | (63074459, 40), 90 | (63074460, 41), 91 | (63074519, 41), 92 | (63074520, 42), 93 | (63074579, 42), 94 | (63074580, 43), 95 | (63074639, 43), 96 | (63074640, 44), 97 | (63074699, 44), 98 | (63074700, 45), 99 | (63074759, 45), 100 | (63074760, 46), 101 | (63074819, 46), 102 | (63074820, 47), 103 | (63074879, 47), 104 | (63074880, 48), 105 | (63074939, 48), 106 | (63074940, 49), 107 | (63074999, 49), 108 | (63075000, 50), 109 | (63075059, 50), 110 | (63075060, 51), 111 | (63075119, 51), 112 | (63075120, 52), 113 | (63075179, 52), 114 | (63075180, 53), 115 | (63075239, 53), 116 | (63075240, 54), 117 | (63075299, 54), 118 | (63075300, 55), 119 | (63075359, 55), 120 | (63075360, 56), 121 | (63075419, 56), 122 | (63075420, 57), 123 | (63075479, 57), 124 | (63075480, 58), 125 | (63075539, 58), 126 | (63075540, 59), 127 | (63075599, 59), 128 | (63075600, 0), 129 | ), 130 | ) 131 | def test_get_minute_from_timestamp(deployed_contracts, timestamp, minute): 132 | crontab = deployed_contracts.DateTime 133 | assert crontab.getMinute(timestamp) == minute 134 | -------------------------------------------------------------------------------- /contracts/DateTime.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.16; 2 | 3 | contract DateTime { 4 | /* 5 | * Date and Time utilities for ethereum contracts 6 | * 7 | */ 8 | struct _DateTime { 9 | uint16 year; 10 | uint8 month; 11 | uint8 day; 12 | uint8 hour; 13 | uint8 minute; 14 | uint8 second; 15 | uint8 weekday; 16 | } 17 | 18 | uint constant DAY_IN_SECONDS = 86400; 19 | uint constant YEAR_IN_SECONDS = 31536000; 20 | uint constant LEAP_YEAR_IN_SECONDS = 31622400; 21 | 22 | uint constant HOUR_IN_SECONDS = 3600; 23 | uint constant MINUTE_IN_SECONDS = 60; 24 | 25 | uint16 constant ORIGIN_YEAR = 1970; 26 | 27 | function isLeapYear(uint16 year) public pure returns (bool) { 28 | if (year % 4 != 0) { 29 | return false; 30 | } 31 | if (year % 100 != 0) { 32 | return true; 33 | } 34 | if (year % 400 != 0) { 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | function leapYearsBefore(uint year) public pure returns (uint) { 41 | year -= 1; 42 | return year / 4 - year / 100 + year / 400; 43 | } 44 | 45 | function getDaysInMonth(uint8 month, uint16 year) public pure returns (uint8) { 46 | if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { 47 | return 31; 48 | } 49 | else if (month == 4 || month == 6 || month == 9 || month == 11) { 50 | return 30; 51 | } 52 | else if (isLeapYear(year)) { 53 | return 29; 54 | } 55 | else { 56 | return 28; 57 | } 58 | } 59 | 60 | function parseTimestamp(uint timestamp) internal pure returns (_DateTime dt) { 61 | uint secondsAccountedFor = 0; 62 | uint buf; 63 | uint8 i; 64 | 65 | // Year 66 | dt.year = getYear(timestamp); 67 | buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR); 68 | 69 | secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf; 70 | secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf); 71 | 72 | // Month 73 | uint secondsInMonth; 74 | for (i = 1; i <= 12; i++) { 75 | secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year); 76 | if (secondsInMonth + secondsAccountedFor > timestamp) { 77 | dt.month = i; 78 | break; 79 | } 80 | secondsAccountedFor += secondsInMonth; 81 | } 82 | 83 | // Day 84 | for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) { 85 | if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) { 86 | dt.day = i; 87 | break; 88 | } 89 | secondsAccountedFor += DAY_IN_SECONDS; 90 | } 91 | 92 | // Hour 93 | dt.hour = getHour(timestamp); 94 | 95 | // Minute 96 | dt.minute = getMinute(timestamp); 97 | 98 | // Second 99 | dt.second = getSecond(timestamp); 100 | 101 | // Day of week. 102 | dt.weekday = getWeekday(timestamp); 103 | } 104 | 105 | function getYear(uint timestamp) public pure returns (uint16) { 106 | uint secondsAccountedFor = 0; 107 | uint16 year; 108 | uint numLeapYears; 109 | 110 | // Year 111 | year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS); 112 | numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR); 113 | 114 | secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears; 115 | secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears); 116 | 117 | while (secondsAccountedFor > timestamp) { 118 | if (isLeapYear(uint16(year - 1))) { 119 | secondsAccountedFor -= LEAP_YEAR_IN_SECONDS; 120 | } 121 | else { 122 | secondsAccountedFor -= YEAR_IN_SECONDS; 123 | } 124 | year -= 1; 125 | } 126 | return year; 127 | } 128 | 129 | function getMonth(uint timestamp) public pure returns (uint8) { 130 | return parseTimestamp(timestamp).month; 131 | } 132 | 133 | function getDay(uint timestamp) public pure returns (uint8) { 134 | return parseTimestamp(timestamp).day; 135 | } 136 | 137 | function getHour(uint timestamp) public pure returns (uint8) { 138 | return uint8((timestamp / 60 / 60) % 24); 139 | } 140 | 141 | function getMinute(uint timestamp) public pure returns (uint8) { 142 | return uint8((timestamp / 60) % 60); 143 | } 144 | 145 | function getSecond(uint timestamp) public pure returns (uint8) { 146 | return uint8(timestamp % 60); 147 | } 148 | 149 | function getWeekday(uint timestamp) public pure returns (uint8) { 150 | return uint8((timestamp / DAY_IN_SECONDS + 4) % 7); 151 | } 152 | 153 | function toTimestamp(uint16 year, uint8 month, uint8 day) public pure returns (uint timestamp) { 154 | return toTimestamp(year, month, day, 0, 0, 0); 155 | } 156 | 157 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) public pure returns (uint timestamp) { 158 | return toTimestamp(year, month, day, hour, 0, 0); 159 | } 160 | 161 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) public pure returns (uint timestamp) { 162 | return toTimestamp(year, month, day, hour, minute, 0); 163 | } 164 | 165 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) public pure returns (uint timestamp) { 166 | uint16 i; 167 | 168 | // Year 169 | for (i = ORIGIN_YEAR; i < year; i++) { 170 | if (isLeapYear(i)) { 171 | timestamp += LEAP_YEAR_IN_SECONDS; 172 | } 173 | else { 174 | timestamp += YEAR_IN_SECONDS; 175 | } 176 | } 177 | 178 | // Month 179 | uint8[12] memory monthDayCounts; 180 | monthDayCounts[0] = 31; 181 | if (isLeapYear(year)) { 182 | monthDayCounts[1] = 29; 183 | } 184 | else { 185 | monthDayCounts[1] = 28; 186 | } 187 | monthDayCounts[2] = 31; 188 | monthDayCounts[3] = 30; 189 | monthDayCounts[4] = 31; 190 | monthDayCounts[5] = 30; 191 | monthDayCounts[6] = 31; 192 | monthDayCounts[7] = 31; 193 | monthDayCounts[8] = 30; 194 | monthDayCounts[9] = 31; 195 | monthDayCounts[10] = 30; 196 | monthDayCounts[11] = 31; 197 | 198 | for (i = 1; i < month; i++) { 199 | timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1]; 200 | } 201 | 202 | // Day 203 | timestamp += DAY_IN_SECONDS * (day - 1); 204 | 205 | // Hour 206 | timestamp += HOUR_IN_SECONDS * (hour); 207 | 208 | // Minute 209 | timestamp += MINUTE_IN_SECONDS * (minute); 210 | 211 | // Second 212 | timestamp += second; 213 | 214 | return timestamp; 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /tests/datetime/test_year.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | 5 | @pytest.mark.parametrize( 6 | 'timestamp,year', 7 | ( 8 | (0, 1970), 9 | (31536000, 1971), 10 | (31535999, 1970), 11 | (63072000, 1972), 12 | (63071999, 1971), 13 | (94694400, 1973), 14 | (94694399, 1972), 15 | (126230400, 1974), 16 | (126230399, 1973), 17 | (157766400, 1975), 18 | (157766399, 1974), 19 | (189302400, 1976), 20 | (189302399, 1975), 21 | (220924800, 1977), 22 | (220924799, 1976), 23 | (252460800, 1978), 24 | (252460799, 1977), 25 | (283996800, 1979), 26 | (283996799, 1978), 27 | (315532800, 1980), 28 | (315532799, 1979), 29 | (347155200, 1981), 30 | (347155199, 1980), 31 | (378691200, 1982), 32 | (378691199, 1981), 33 | (410227200, 1983), 34 | (410227199, 1982), 35 | (441763200, 1984), 36 | (441763199, 1983), 37 | (473385600, 1985), 38 | (473385599, 1984), 39 | (504921600, 1986), 40 | (504921599, 1985), 41 | (536457600, 1987), 42 | (536457599, 1986), 43 | (567993600, 1988), 44 | (567993599, 1987), 45 | (599616000, 1989), 46 | (599615999, 1988), 47 | (631152000, 1990), 48 | (631151999, 1989), 49 | (662688000, 1991), 50 | (662687999, 1990), 51 | (694224000, 1992), 52 | (694223999, 1991), 53 | (725846400, 1993), 54 | (725846399, 1992), 55 | (757382400, 1994), 56 | (757382399, 1993), 57 | (788918400, 1995), 58 | (788918399, 1994), 59 | (820454400, 1996), 60 | (820454399, 1995), 61 | (852076800, 1997), 62 | (852076799, 1996), 63 | (883612800, 1998), 64 | (883612799, 1997), 65 | (915148800, 1999), 66 | (915148799, 1998), 67 | (946684800, 2000), 68 | (946684799, 1999), 69 | (978307200, 2001), 70 | (978307199, 2000), 71 | (1009843200, 2002), 72 | (1009843199, 2001), 73 | (1041379200, 2003), 74 | (1041379199, 2002), 75 | (1072915200, 2004), 76 | (1072915199, 2003), 77 | (1104537600, 2005), 78 | (1104537599, 2004), 79 | (1136073600, 2006), 80 | (1136073599, 2005), 81 | (1167609600, 2007), 82 | (1167609599, 2006), 83 | (1199145600, 2008), 84 | (1199145599, 2007), 85 | (1230768000, 2009), 86 | (1230767999, 2008), 87 | (1262304000, 2010), 88 | (1262303999, 2009), 89 | (1293840000, 2011), 90 | (1293839999, 2010), 91 | (1325376000, 2012), 92 | (1325375999, 2011), 93 | (1356998400, 2013), 94 | (1356998399, 2012), 95 | (1388534400, 2014), 96 | (1388534399, 2013), 97 | (1420070400, 2015), 98 | (1420070399, 2014), 99 | (1451606400, 2016), 100 | (1451606399, 2015), 101 | (1483228800, 2017), 102 | (1483228799, 2016), 103 | (1514764800, 2018), 104 | (1514764799, 2017), 105 | (1546300800, 2019), 106 | (1546300799, 2018), 107 | (1577836800, 2020), 108 | (1577836799, 2019), 109 | (1609459200, 2021), 110 | (1609459199, 2020), 111 | (1640995200, 2022), 112 | (1640995199, 2021), 113 | (1672531200, 2023), 114 | (1672531199, 2022), 115 | (1704067200, 2024), 116 | (1704067199, 2023), 117 | (1735689600, 2025), 118 | (1735689599, 2024), 119 | (1767225600, 2026), 120 | (1767225599, 2025), 121 | (1798761600, 2027), 122 | (1798761599, 2026), 123 | (1830297600, 2028), 124 | (1830297599, 2027), 125 | (1861920000, 2029), 126 | (1861919999, 2028), 127 | (1893456000, 2030), 128 | (1893455999, 2029), 129 | (1924992000, 2031), 130 | (1924991999, 2030), 131 | (1956528000, 2032), 132 | (1956527999, 2031), 133 | (1988150400, 2033), 134 | (1988150399, 2032), 135 | (2019686400, 2034), 136 | (2019686399, 2033), 137 | (2051222400, 2035), 138 | (2051222399, 2034), 139 | (2082758400, 2036), 140 | (2082758399, 2035), 141 | (2114380800, 2037), 142 | (2114380799, 2036), 143 | (2145916800, 2038), 144 | (2145916799, 2037), 145 | (2177452800, 2039), 146 | (2177452799, 2038), 147 | (2208988800, 2040), 148 | (2208988799, 2039), 149 | (2240611200, 2041), 150 | (2240611199, 2040), 151 | (2272147200, 2042), 152 | (2272147199, 2041), 153 | (2303683200, 2043), 154 | (2303683199, 2042), 155 | (2335219200, 2044), 156 | (2335219199, 2043), 157 | (2366841600, 2045), 158 | (2366841599, 2044), 159 | (2398377600, 2046), 160 | (2398377599, 2045), 161 | (2429913600, 2047), 162 | (2429913599, 2046), 163 | (2461449600, 2048), 164 | (2461449599, 2047), 165 | (2493072000, 2049), 166 | (2493071999, 2048), 167 | (2524608000, 2050), 168 | (2524607999, 2049), 169 | (2556144000, 2051), 170 | (2556143999, 2050), 171 | (2587680000, 2052), 172 | (2587679999, 2051), 173 | (2619302400, 2053), 174 | (2619302399, 2052), 175 | (2650838400, 2054), 176 | (2650838399, 2053), 177 | (2682374400, 2055), 178 | (2682374399, 2054), 179 | (2713910400, 2056), 180 | (2713910399, 2055), 181 | (2745532800, 2057), 182 | (2745532799, 2056), 183 | (2777068800, 2058), 184 | (2777068799, 2057), 185 | (2808604800, 2059), 186 | (2808604799, 2058), 187 | (2840140800, 2060), 188 | (2840140799, 2059), 189 | (2871763200, 2061), 190 | (2871763199, 2060), 191 | (2903299200, 2062), 192 | (2903299199, 2061), 193 | (2934835200, 2063), 194 | (2934835199, 2062), 195 | (2966371200, 2064), 196 | (2966371199, 2063), 197 | (2997993600, 2065), 198 | (2997993599, 2064), 199 | (3029529600, 2066), 200 | (3029529599, 2065), 201 | (3061065600, 2067), 202 | (3061065599, 2066), 203 | (3092601600, 2068), 204 | (3092601599, 2067), 205 | (3124224000, 2069), 206 | (3124223999, 2068), 207 | (3155760000, 2070), 208 | (3155759999, 2069), 209 | (3187296000, 2071), 210 | (3187295999, 2070), 211 | (3218832000, 2072), 212 | (3218831999, 2071), 213 | (3250454400, 2073), 214 | (3250454399, 2072), 215 | (3281990400, 2074), 216 | (3281990399, 2073), 217 | (3313526400, 2075), 218 | (3313526399, 2074), 219 | (3345062400, 2076), 220 | (3345062399, 2075), 221 | (3376684800, 2077), 222 | (3376684799, 2076), 223 | (3408220800, 2078), 224 | (3408220799, 2077), 225 | (3439756800, 2079), 226 | (3439756799, 2078), 227 | (3471292800, 2080), 228 | (3471292799, 2079), 229 | (3502915200, 2081), 230 | (3502915199, 2080), 231 | (3534451200, 2082), 232 | (3534451199, 2081), 233 | (3565987200, 2083), 234 | (3565987199, 2082), 235 | (3597523200, 2084), 236 | (3597523199, 2083), 237 | (3629145600, 2085), 238 | (3629145599, 2084), 239 | (3660681600, 2086), 240 | (3660681599, 2085), 241 | (3692217600, 2087), 242 | (3692217599, 2086), 243 | (3723753600, 2088), 244 | (3723753599, 2087), 245 | (3755376000, 2089), 246 | (3755375999, 2088), 247 | (3786912000, 2090), 248 | (3786911999, 2089), 249 | (3818448000, 2091), 250 | (3818447999, 2090), 251 | (3849984000, 2092), 252 | (3849983999, 2091), 253 | (3881606400, 2093), 254 | (3881606399, 2092), 255 | (3913142400, 2094), 256 | (3913142399, 2093), 257 | (3944678400, 2095), 258 | (3944678399, 2094), 259 | (3976214400, 2096), 260 | (3976214399, 2095), 261 | (4007836800, 2097), 262 | (4007836799, 2096), 263 | (4039372800, 2098), 264 | (4039372799, 2097), 265 | (4070908800, 2099), 266 | (4070908799, 2098), 267 | (4102444800, 2100), 268 | (4102444799, 2099), 269 | (4133980800, 2101), 270 | (4133980799, 2100), 271 | (4165516800, 2102), 272 | (4165516799, 2101), 273 | (4197052800, 2103), 274 | (4197052799, 2102), 275 | (4228588800, 2104), 276 | (4228588799, 2103), 277 | (4260211200, 2105), 278 | (4260211199, 2104), 279 | (4291747200, 2106), 280 | (4291747199, 2105), 281 | (4323283200, 2107), 282 | (4323283199, 2106), 283 | (4354819200, 2108), 284 | (4354819199, 2107), 285 | (4386441600, 2109), 286 | (4386441599, 2108), 287 | (4417977600, 2110), 288 | (4417977599, 2109), 289 | (4449513600, 2111), 290 | (4449513599, 2110), 291 | (4481049600, 2112), 292 | (4481049599, 2111), 293 | (4512672000, 2113), 294 | (4512671999, 2112), 295 | (4544208000, 2114), 296 | (4544207999, 2113), 297 | (4575744000, 2115), 298 | (4575743999, 2114), 299 | (4607280000, 2116), 300 | (4607279999, 2115), 301 | (4638902400, 2117), 302 | (4638902399, 2116), 303 | (4670438400, 2118), 304 | (4670438399, 2117), 305 | (4701974400, 2119), 306 | (4701974399, 2118), 307 | (4733510400, 2120), 308 | (4733510399, 2119), 309 | (4765132800, 2121), 310 | (4765132799, 2120), 311 | (4796668800, 2122), 312 | (4796668799, 2121), 313 | (4828204800, 2123), 314 | (4828204799, 2122), 315 | (4859740800, 2124), 316 | (4859740799, 2123), 317 | (4891363200, 2125), 318 | (4891363199, 2124), 319 | (4922899200, 2126), 320 | (4922899199, 2125), 321 | (4954435200, 2127), 322 | (4954435199, 2126), 323 | (4985971200, 2128), 324 | (4985971199, 2127), 325 | (5017593600, 2129), 326 | (5017593599, 2128), 327 | (5049129600, 2130), 328 | (5049129599, 2129), 329 | (5080665600, 2131), 330 | (5080665599, 2130), 331 | (5112201600, 2132), 332 | (5112201599, 2131), 333 | (5143824000, 2133), 334 | (5143823999, 2132), 335 | (5175360000, 2134), 336 | (5175359999, 2133), 337 | (5206896000, 2135), 338 | (5206895999, 2134), 339 | (5238432000, 2136), 340 | (5238431999, 2135), 341 | (5270054400, 2137), 342 | (5270054399, 2136), 343 | (5301590400, 2138), 344 | (5301590399, 2137), 345 | (5333126400, 2139), 346 | (5333126399, 2138), 347 | (5364662400, 2140), 348 | (5364662399, 2139), 349 | (5396284800, 2141), 350 | (5396284799, 2140), 351 | (5427820800, 2142), 352 | (5427820799, 2141), 353 | (5459356800, 2143), 354 | (5459356799, 2142), 355 | (5490892800, 2144), 356 | (5490892799, 2143), 357 | (5522515200, 2145), 358 | (5522515199, 2144), 359 | (5554051200, 2146), 360 | (5554051199, 2145), 361 | (5585587200, 2147), 362 | (5585587199, 2146), 363 | (5617123200, 2148), 364 | (5617123199, 2147), 365 | (5648745600, 2149), 366 | (5648745599, 2148), 367 | (5680281600, 2150), 368 | (5680281599, 2149), 369 | (5711817600, 2151), 370 | (5711817599, 2150), 371 | (5743353600, 2152), 372 | (5743353599, 2151), 373 | (5774976000, 2153), 374 | (5774975999, 2152), 375 | (5806512000, 2154), 376 | (5806511999, 2153), 377 | (5838048000, 2155), 378 | (5838047999, 2154), 379 | (5869584000, 2156), 380 | (5869583999, 2155), 381 | (5901206400, 2157), 382 | (5901206399, 2156), 383 | (5932742400, 2158), 384 | (5932742399, 2157), 385 | (5964278400, 2159), 386 | (5964278399, 2158), 387 | (5995814400, 2160), 388 | (5995814399, 2159), 389 | (6027436800, 2161), 390 | (6027436799, 2160), 391 | (6058972800, 2162), 392 | (6058972799, 2161), 393 | (6090508800, 2163), 394 | (6090508799, 2162), 395 | (6122044800, 2164), 396 | (6122044799, 2163), 397 | (6153667200, 2165), 398 | (6153667199, 2164), 399 | (6185203200, 2166), 400 | (6185203199, 2165), 401 | (6216739200, 2167), 402 | (6216739199, 2166), 403 | (6248275200, 2168), 404 | (6248275199, 2167), 405 | (6279897600, 2169), 406 | (6279897599, 2168), 407 | (6311433600, 2170), 408 | (6311433599, 2169), 409 | (6342969600, 2171), 410 | (6342969599, 2170), 411 | (6374505600, 2172), 412 | (6374505599, 2171), 413 | (6406128000, 2173), 414 | (6406127999, 2172), 415 | (6437664000, 2174), 416 | (6437663999, 2173), 417 | (6469200000, 2175), 418 | (6469199999, 2174), 419 | (6500736000, 2176), 420 | (6500735999, 2175), 421 | (6532358400, 2177), 422 | (6532358399, 2176), 423 | (6563894400, 2178), 424 | (6563894399, 2177), 425 | (6595430400, 2179), 426 | (6595430399, 2178), 427 | (6626966400, 2180), 428 | (6626966399, 2179), 429 | (6658588800, 2181), 430 | (6658588799, 2180), 431 | (6690124800, 2182), 432 | (6690124799, 2181), 433 | (6721660800, 2183), 434 | (6721660799, 2182), 435 | (6753196800, 2184), 436 | (6753196799, 2183), 437 | (6784819200, 2185), 438 | (6784819199, 2184), 439 | (6816355200, 2186), 440 | (6816355199, 2185), 441 | (6847891200, 2187), 442 | (6847891199, 2186), 443 | (6879427200, 2188), 444 | (6879427199, 2187), 445 | (6911049600, 2189), 446 | (6911049599, 2188), 447 | (6942585600, 2190), 448 | (6942585599, 2189), 449 | (6974121600, 2191), 450 | (6974121599, 2190), 451 | (7005657600, 2192), 452 | (7005657599, 2191), 453 | (7037280000, 2193), 454 | (7037279999, 2192), 455 | (7068816000, 2194), 456 | (7068815999, 2193), 457 | (7100352000, 2195), 458 | (7100351999, 2194), 459 | (7131888000, 2196), 460 | (7131887999, 2195), 461 | (7163510400, 2197), 462 | (7163510399, 2196), 463 | (7195046400, 2198), 464 | (7195046399, 2197), 465 | (7226582400, 2199), 466 | (7226582399, 2198), 467 | (7258118400, 2200), 468 | (7258118399, 2199), 469 | (7289654400, 2201), 470 | (7289654399, 2200), 471 | (7321190400, 2202), 472 | (7321190399, 2201), 473 | (7352726400, 2203), 474 | (7352726399, 2202), 475 | (7384262400, 2204), 476 | (7384262399, 2203), 477 | (7415884800, 2205), 478 | (7415884799, 2204), 479 | (7447420800, 2206), 480 | (7447420799, 2205), 481 | (7478956800, 2207), 482 | (7478956799, 2206), 483 | (7510492800, 2208), 484 | (7510492799, 2207), 485 | (7542115200, 2209), 486 | (7542115199, 2208), 487 | (7573651200, 2210), 488 | (7573651199, 2209), 489 | (7605187200, 2211), 490 | (7605187199, 2210), 491 | (7636723200, 2212), 492 | (7636723199, 2211), 493 | (7668345600, 2213), 494 | (7668345599, 2212), 495 | (7699881600, 2214), 496 | (7699881599, 2213), 497 | (7731417600, 2215), 498 | (7731417599, 2214), 499 | (7762953600, 2216), 500 | (7762953599, 2215), 501 | (7794576000, 2217), 502 | (7794575999, 2216), 503 | (7826112000, 2218), 504 | (7826111999, 2217), 505 | (7857648000, 2219), 506 | (7857647999, 2218), 507 | (7889184000, 2220), 508 | (7889183999, 2219), 509 | (7920806400, 2221), 510 | (7920806399, 2220), 511 | (7952342400, 2222), 512 | (7952342399, 2221), 513 | (7983878400, 2223), 514 | (7983878399, 2222), 515 | (8015414400, 2224), 516 | (8015414399, 2223), 517 | (8047036800, 2225), 518 | (8047036799, 2224), 519 | (8078572800, 2226), 520 | (8078572799, 2225), 521 | (8110108800, 2227), 522 | (8110108799, 2226), 523 | (8141644800, 2228), 524 | (8141644799, 2227), 525 | (8173267200, 2229), 526 | (8173267199, 2228), 527 | (8204803200, 2230), 528 | (8204803199, 2229), 529 | (8236339200, 2231), 530 | (8236339199, 2230), 531 | (8267875200, 2232), 532 | (8267875199, 2231), 533 | (8299497600, 2233), 534 | (8299497599, 2232), 535 | (8331033600, 2234), 536 | (8331033599, 2233), 537 | (8362569600, 2235), 538 | (8362569599, 2234), 539 | (8394105600, 2236), 540 | (8394105599, 2235), 541 | (8425728000, 2237), 542 | (8425727999, 2236), 543 | (8457264000, 2238), 544 | (8457263999, 2237), 545 | (8488800000, 2239), 546 | (8488799999, 2238), 547 | (8520336000, 2240), 548 | (8520335999, 2239), 549 | (8551958400, 2241), 550 | (8551958399, 2240), 551 | (8583494400, 2242), 552 | (8583494399, 2241), 553 | (8615030400, 2243), 554 | (8615030399, 2242), 555 | (8646566400, 2244), 556 | (8646566399, 2243), 557 | (8678188800, 2245), 558 | (8678188799, 2244), 559 | (8709724800, 2246), 560 | (8709724799, 2245), 561 | (8741260800, 2247), 562 | (8741260799, 2246), 563 | (8772796800, 2248), 564 | (8772796799, 2247), 565 | (8804419200, 2249), 566 | (8804419199, 2248), 567 | (8835955200, 2250), 568 | (8835955199, 2249), 569 | (8867491200, 2251), 570 | (8867491199, 2250), 571 | (8899027200, 2252), 572 | (8899027199, 2251), 573 | (8930649600, 2253), 574 | (8930649599, 2252), 575 | (8962185600, 2254), 576 | (8962185599, 2253), 577 | (8993721600, 2255), 578 | (8993721599, 2254), 579 | (9025257600, 2256), 580 | (9025257599, 2255), 581 | (9056880000, 2257), 582 | (9056879999, 2256), 583 | (9088416000, 2258), 584 | (9088415999, 2257), 585 | (9119952000, 2259), 586 | (9119951999, 2258), 587 | (9151488000, 2260), 588 | (9151487999, 2259), 589 | (9183110400, 2261), 590 | (9183110399, 2260), 591 | (9214646400, 2262), 592 | (9214646399, 2261), 593 | (9246182400, 2263), 594 | (9246182399, 2262), 595 | (9277718400, 2264), 596 | (9277718399, 2263), 597 | (9309340800, 2265), 598 | (9309340799, 2264), 599 | (9340876800, 2266), 600 | (9340876799, 2265), 601 | (9372412800, 2267), 602 | (9372412799, 2266), 603 | (9403948800, 2268), 604 | (9403948799, 2267), 605 | (9435571200, 2269), 606 | (9435571199, 2268), 607 | (9467107200, 2270), 608 | (9467107199, 2269), 609 | (9498643200, 2271), 610 | (9498643199, 2270), 611 | (9530179200, 2272), 612 | (9530179199, 2271), 613 | (9561801600, 2273), 614 | (9561801599, 2272), 615 | (9593337600, 2274), 616 | (9593337599, 2273), 617 | (9624873600, 2275), 618 | (9624873599, 2274), 619 | (9656409600, 2276), 620 | (9656409599, 2275), 621 | (9688032000, 2277), 622 | (9688031999, 2276), 623 | (9719568000, 2278), 624 | (9719567999, 2277), 625 | (9751104000, 2279), 626 | (9751103999, 2278), 627 | (9782640000, 2280), 628 | (9782639999, 2279), 629 | (9814262400, 2281), 630 | (9814262399, 2280), 631 | (9845798400, 2282), 632 | (9845798399, 2281), 633 | (9877334400, 2283), 634 | (9877334399, 2282), 635 | (9908870400, 2284), 636 | (9908870399, 2283), 637 | (9940492800, 2285), 638 | (9940492799, 2284), 639 | (9972028800, 2286), 640 | (9972028799, 2285), 641 | (10003564800, 2287), 642 | (10003564799, 2286), 643 | (10035100800, 2288), 644 | (10035100799, 2287), 645 | (10066723200, 2289), 646 | (10066723199, 2288), 647 | (10098259200, 2290), 648 | (10098259199, 2289), 649 | (10129795200, 2291), 650 | (10129795199, 2290), 651 | (10161331200, 2292), 652 | (10161331199, 2291), 653 | (10192953600, 2293), 654 | (10192953599, 2292), 655 | (10224489600, 2294), 656 | (10224489599, 2293), 657 | (10256025600, 2295), 658 | (10256025599, 2294), 659 | (10287561600, 2296), 660 | (10287561599, 2295), 661 | (10319184000, 2297), 662 | (10319183999, 2296), 663 | (10350720000, 2298), 664 | (10350719999, 2297), 665 | (10382256000, 2299), 666 | (10382255999, 2298), 667 | (10413792000, 2300), 668 | (10413791999, 2299), 669 | (10445328000, 2301), 670 | (10445327999, 2300), 671 | (10476864000, 2302), 672 | (10476863999, 2301), 673 | (10508400000, 2303), 674 | (10508399999, 2302), 675 | (10539936000, 2304), 676 | (10539935999, 2303), 677 | (10571558400, 2305), 678 | (10571558399, 2304), 679 | (10603094400, 2306), 680 | (10603094399, 2305), 681 | (10634630400, 2307), 682 | (10634630399, 2306), 683 | (10666166400, 2308), 684 | (10666166399, 2307), 685 | (10697788800, 2309), 686 | (10697788799, 2308), 687 | (10729324800, 2310), 688 | (10729324799, 2309), 689 | (10760860800, 2311), 690 | (10760860799, 2310), 691 | (10792396800, 2312), 692 | (10792396799, 2311), 693 | (10824019200, 2313), 694 | (10824019199, 2312), 695 | (10855555200, 2314), 696 | (10855555199, 2313), 697 | (10887091200, 2315), 698 | (10887091199, 2314), 699 | (10918627200, 2316), 700 | (10918627199, 2315), 701 | (10950249600, 2317), 702 | (10950249599, 2316), 703 | (10981785600, 2318), 704 | (10981785599, 2317), 705 | (11013321600, 2319), 706 | (11013321599, 2318), 707 | (11044857600, 2320), 708 | (11044857599, 2319), 709 | (11076480000, 2321), 710 | (11076479999, 2320), 711 | (11108016000, 2322), 712 | (11108015999, 2321), 713 | (11139552000, 2323), 714 | (11139551999, 2322), 715 | (11171088000, 2324), 716 | (11171087999, 2323), 717 | (11202710400, 2325), 718 | (11202710399, 2324), 719 | (11234246400, 2326), 720 | (11234246399, 2325), 721 | (11265782400, 2327), 722 | (11265782399, 2326), 723 | (11297318400, 2328), 724 | (11297318399, 2327), 725 | (11328940800, 2329), 726 | (11328940799, 2328), 727 | (11360476800, 2330), 728 | (11360476799, 2329), 729 | (11392012800, 2331), 730 | (11392012799, 2330), 731 | (11423548800, 2332), 732 | (11423548799, 2331), 733 | (11455171200, 2333), 734 | (11455171199, 2332), 735 | (11486707200, 2334), 736 | (11486707199, 2333), 737 | (11518243200, 2335), 738 | (11518243199, 2334), 739 | (11549779200, 2336), 740 | (11549779199, 2335), 741 | (11581401600, 2337), 742 | (11581401599, 2336), 743 | (11612937600, 2338), 744 | (11612937599, 2337), 745 | (11644473600, 2339), 746 | (11644473599, 2338), 747 | (11676009600, 2340), 748 | (11676009599, 2339), 749 | (11707632000, 2341), 750 | (11707631999, 2340), 751 | (11739168000, 2342), 752 | (11739167999, 2341), 753 | (11770704000, 2343), 754 | (11770703999, 2342), 755 | (11802240000, 2344), 756 | (11802239999, 2343), 757 | (11833862400, 2345), 758 | (11833862399, 2344), 759 | (11865398400, 2346), 760 | (11865398399, 2345), 761 | (11896934400, 2347), 762 | (11896934399, 2346), 763 | (11928470400, 2348), 764 | (11928470399, 2347), 765 | (11960092800, 2349), 766 | (11960092799, 2348), 767 | (11991628800, 2350), 768 | (11991628799, 2349), 769 | (12023164800, 2351), 770 | (12023164799, 2350), 771 | (12054700800, 2352), 772 | (12054700799, 2351), 773 | (12086323200, 2353), 774 | (12086323199, 2352), 775 | (12117859200, 2354), 776 | (12117859199, 2353), 777 | (12149395200, 2355), 778 | (12149395199, 2354), 779 | (12180931200, 2356), 780 | (12180931199, 2355), 781 | (12212553600, 2357), 782 | (12212553599, 2356), 783 | (12244089600, 2358), 784 | (12244089599, 2357), 785 | (12275625600, 2359), 786 | (12275625599, 2358), 787 | (12307161600, 2360), 788 | (12307161599, 2359), 789 | (12338784000, 2361), 790 | (12338783999, 2360), 791 | (12370320000, 2362), 792 | (12370319999, 2361), 793 | (12401856000, 2363), 794 | (12401855999, 2362), 795 | (12433392000, 2364), 796 | (12433391999, 2363), 797 | (12465014400, 2365), 798 | (12465014399, 2364), 799 | (12496550400, 2366), 800 | (12496550399, 2365), 801 | (12528086400, 2367), 802 | (12528086399, 2366), 803 | (12559622400, 2368), 804 | (12559622399, 2367), 805 | (12591244800, 2369), 806 | (12591244799, 2368), 807 | (12622780800, 2370), 808 | (12622780799, 2369), 809 | (12654316800, 2371), 810 | (12654316799, 2370), 811 | (12685852800, 2372), 812 | (12685852799, 2371), 813 | (12717475200, 2373), 814 | (12717475199, 2372), 815 | (12749011200, 2374), 816 | (12749011199, 2373), 817 | (12780547200, 2375), 818 | (12780547199, 2374), 819 | (12812083200, 2376), 820 | (12812083199, 2375), 821 | (12843705600, 2377), 822 | (12843705599, 2376), 823 | (12875241600, 2378), 824 | (12875241599, 2377), 825 | (12906777600, 2379), 826 | (12906777599, 2378), 827 | (12938313600, 2380), 828 | (12938313599, 2379), 829 | (12969936000, 2381), 830 | (12969935999, 2380), 831 | (13001472000, 2382), 832 | (13001471999, 2381), 833 | (13033008000, 2383), 834 | (13033007999, 2382), 835 | (13064544000, 2384), 836 | (13064543999, 2383), 837 | (13096166400, 2385), 838 | (13096166399, 2384), 839 | (13127702400, 2386), 840 | (13127702399, 2385), 841 | (13159238400, 2387), 842 | (13159238399, 2386), 843 | (13190774400, 2388), 844 | (13190774399, 2387), 845 | (13222396800, 2389), 846 | (13222396799, 2388), 847 | (13253932800, 2390), 848 | (13253932799, 2389), 849 | (13285468800, 2391), 850 | (13285468799, 2390), 851 | (13317004800, 2392), 852 | (13317004799, 2391), 853 | (13348627200, 2393), 854 | (13348627199, 2392), 855 | (13380163200, 2394), 856 | (13380163199, 2393), 857 | (13411699200, 2395), 858 | (13411699199, 2394), 859 | (13443235200, 2396), 860 | (13443235199, 2395), 861 | (13474857600, 2397), 862 | (13474857599, 2396), 863 | (13506393600, 2398), 864 | (13506393599, 2397), 865 | (13537929600, 2399), 866 | (13537929599, 2398), 867 | ) 868 | ) 869 | def test_get_year_from_timestamp(deployed_contracts, timestamp, year): 870 | crontab = deployed_contracts.DateTime 871 | assert crontab.getYear(timestamp) == year 872 | --------------------------------------------------------------------------------