📄 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}