Работа с датой и временем в каждом языке программирования всегда имеет свою специфику. Разберем некоторые моменты и приведем примеры для языка Solidity, который используется для создания децентрализованных приложений на базе блокчейна Ethereum.
Переменные с типом Дата
Даты в Solidity хранятся в переменных типа uint. Глобальная переменная now будет возвращать дату и время в формате unix последнего блока (количество секунд, прошедших с 1 января 1970 года).
uint lastUpdated; // Установить в переменную `lastUpdated` текущее время function updateTimestamp() public { lastUpdated = now; }
Время Unix традиционно хранится в виде 32-битного числа. Это приведет к проблеме «2038 год», когда 32-битные временные метки unix будут переполнены, потому что они не смогут сохранить это большое число. Чтобы избежать этой проблемы, мы можем вместо этого использовать 64-битный номер, хотя это потребует более высокой платы за газ для наших контрактов.
Преобразование JavaScript даты в дату Solidity
Если мы хотим сохранить дату в смарт-контракте со значением, переданным из веб-приложения, то нам нужно преобразовать дату JavaScript в формат unix, которую мы будем хранить в смарт-контракте как переменную uint.
// Получаем объект JS с текущей датой const today = new Date(); // ⚠️ JS возвращает время в миллисекундах const mseconds = today.getTime(); // Разделим на 1000, чтобы получить время в секундах const seconds = Math.floor(mseconds / 1000); // Запишем все эти действия в одну строку const dateInSecs = Math.floor(new Date().getTime() / 1000);
Получив количество секунд, мы можем передать это значение в наш смарт-контракт, используя Ethers.js или Web3.js.
Единицы даты и времени
Solidity предоставляет некоторые встроенные единицы измерения времени: seconds, minutes, hours, days, weeks и years. Эти единицы измерения будут преобразованы в секунды за указанный промежуток времени. Например, 1 minutes — это 60, 1 hours — это 3600 (60 секунд х 60 минут) и т. д.
uint a = 3 hours; // 10800 или 3*60*60 uint b = 5 minutes // 300 или 5*60 uint d = 2 weeks // 1209600 или 2*7*24*60*60
Эти единицы очень полезны для работы с датами и временем в наших смарт-контрактах, поскольку они позволяют нам использовать математические операторы, такие как + и –.
Как вычислить количество дней между двумя датами?
uint startDate = 1638352800; // 2012-12-01 10:00:00 uint endDate = 1638871200; // 2012-12-07 10:00:00 uint daysDiff = (endDate - startDate) / 60 / 60 / 24; // 6 days
Как сравнить даты в Solidity?
Можно использовать операторы < или > для сравнения двух дат. Это позволяет нам легко сравнивать две даты или проверять, была ли дата раньше или позже другой:
uint date_1 = 1638352800; // 2012-12-01 10:00:00 uint date_2 = 1638871200; // 2012-12-07 10:00:00 function isBefore(uint _date1, uint _date2) returns (boolean) { if(date_1 < date_2) return true; return false; }
Как проверить истекло ли время?
Код ниже показывает, как проверить, прошло ли 10 минут с момента развертывания контракта:
pragma solidity >=0.8.1 contract MyContract { uint deployDate; constructor(){ deployDate = now; } // Будет возвращено `true` если прошло 10 минут с момента деплоя смарт-контракта function tenMinutesHavePassed() public view returns (bool) { return (now >= (deployDate + 10 minutes)); } }
Как увеличить или уменьшить количество дней от текущей даты?
uint date = 1638352800; // 2012-12-01 10:00:00 uint later = date + 1 days; uint nextYear = date + 1 years; uint before = date - 3 days; uint prevWeek = date - 1 weeks;