📄 DateUtils.sol
D-OPEN SOVEREIGN
Documentation & Insights
@dev Gets the last 3 digits of current year and current month (1-12)1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 *
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 *
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15
16// SPDX-License-Identifier: Apache-2.0
17pragma solidity ^0.8.24;
18
19library DateUtils {
20 // Hoist constants to file scope (saves runtime gas and bytecode size)
21 uint256 internal constant SECONDS_PER_DAY = 24 * 60 * 60;
22 uint256 internal constant SECONDS_PER_YEAR = 365 * SECONDS_PER_DAY;
23 uint256 internal constant SECONDS_PER_MONTH = SECONDS_PER_YEAR / 12;
24
25 function uintToString(uint _i) internal pure returns (string memory str) {
26
27 if (_i == 0) {
28 return "0";
29 }
30 uint256 j = _i;
31 uint256 length;
32 while (j != 0) {
33 length++;
34 j /= 10;
35 }
36 bytes memory bstr = new bytes(length);
37 uint256 k = length;
38 j = _i;
39 while (j != 0) {
40 bstr[--k] = bytes1(uint8(48 + j % 10));
41 j /= 10;
42 }
43 str = string(bstr);
44 }
45
46 function uint16ToString(uint16 value) internal pure returns (string memory) {
47 return uintToString(value);
48
49// if (value == 0) {
50// return "0";
51// }
52// uint16 temp = value;
53// uint256 digits;
54// while (temp != 0) {
55// unchecked { digits++; temp /= 10; }
56// }
57// bytes memory buffer = new bytes(digits);
58// while (value != 0) {
59// unchecked {
60// digits -= 1;
61// buffer[digits] = bytes1(uint8(48 + (value % 10)));
62// value /= 10;
63// }
64// }
65// return string(buffer);
66 }
67
68 function uint8ToString(uint8 value) internal pure returns (string memory) {
69 return uintToString(value);
70// if (value == 0) return "0";
71//
72// uint8 temp = value;
73// uint256 digits;
74//
75// while (temp != 0) {
76// unchecked { digits++; temp /= 10; }
77// }
78//
79// bytes memory buffer = new bytes(digits);
80//
81// while (value != 0) {
82// unchecked {
83// digits -= 1;
84// buffer[digits] = bytes1(uint8(48 + (value % 10)));
85// value /= 10;
86// }
87// }
88//
89// return string(buffer);
90 }
91
92 function getYearMonthString() internal view returns (string memory yearMonth) {
93 (uint16 year, uint8 month) = DateUtils.getCurrentYearAndMonth();
94 string memory word = string.concat(DateUtils.uint16ToString(year), "-");
95 word = string.concat(word, DateUtils.uint8ToString(month));
96 return word;
97 }
98 /**
99 * @dev Gets the last 3 digits of current year and current month (1-12)
100 */
101 function getCurrentYearAndMonth() internal view returns (uint16 year, uint8 month) {
102 uint256 timestamp = block.timestamp;
103
104 // Convert timestamp to days since epoch
105 uint256 daysSinceEpoch = timestamp / SECONDS_PER_DAY;
106
107 // Epoch started on Thursday, Jan 1, 1970
108 // Calculate approximate year (this is a simplified calculation)
109 uint16 currentYear = 1970;
110 uint256 remainingDays = daysSinceEpoch;
111
112 // More accurate year calculation
113 while (remainingDays >= 365) {
114 if (isLeapYear(currentYear)) {
115 if (remainingDays >= 366) {
116 remainingDays -= 366;
117 currentYear++;
118 } else {
119 break;
120 }
121 } else {
122 remainingDays -= 365;
123 currentYear++;
124 }
125 }
126
127
128 // Calculate month from remaining days
129 uint8 monthNum = calculateMonthFromDays(uint16(remainingDays), isLeapYear(currentYear));
130
131 return (currentYear, monthNum);
132 }
133
134 function isLeapYear(uint256 year) internal pure returns (bool) {
135 return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
136 }
137
138 function calculateMonthFromDays(uint16 dayInYear, bool leapYear) internal pure returns (uint8) {
139 uint8[12] memory daysInMonth;
140 if (leapYear) {
141 daysInMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
142 } else {
143 daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
144 }
145
146 uint16 totalDays = 0;
147 for (uint8 i = 0; i < 12; i++) {
148 if (dayInYear < totalDays + uint16(daysInMonth[i])) {
149 return i + 1; // Return 1-based month
150 }
151 totalDays += uint16(daysInMonth[i]);
152 }
153 return 12; // December as fallback
154 }
155
156}