Surgebound

R4 Moon SPI Screen With Wifi

Oct 8th, 2026
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 13.55 KB | Source Code | 0 0
  1. #include <Wire.h>
  2. #include <SPI.h>
  3. #include <WiFiS3.h>
  4. #include <U8g2lib.h>
  5. #include <RTClib.h>
  6.  
  7. // Enter your 2.4 GHz Wi-Fi details here.
  8. const char WIFI_SSID[] = "YOUR_WIFI_NAME";
  9. const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
  10.  
  11. // SSD1315 128x64 OLED using its SSD1306-compatible command set.
  12. // Four-wire hardware SPI connections on the Arduino UNO R4 WiFi:
  13. // OLED SCK -> D13, OLED SDA/DIN -> D11, CS -> D10, DC -> D9, RES -> D4.
  14. // D12/CIPO/MISO is not used because the OLED only receives data.
  15. constexpr uint8_t OLED_CS_PIN = 10;
  16. constexpr uint8_t OLED_DC_PIN = 9;
  17. constexpr uint8_t OLED_RESET_PIN = 4;
  18.  
  19. U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(
  20.     U8G2_R0, OLED_CS_PIN, OLED_DC_PIN, OLED_RESET_PIN);
  21.  
  22. RTC_DS3231 rtc;
  23. bool rtcReady = false;
  24.  
  25. // Six separately controlled LEDs, ordered from the moon's left edge to right.
  26. // Each bare LED needs its own resistor (470 ohms is a safe starting value).
  27. constexpr uint8_t MOON_LED_COUNT = 6;
  28. const uint8_t MOON_LED_PINS[MOON_LED_COUNT] = {2, 3, 5, 6, 7, 8};
  29. constexpr bool LED_ACTIVE_HIGH = true;  // false for common-positive wiring
  30.  
  31. // Bit 0 is the leftmost LED; bit 5 is the rightmost LED.
  32. // Order: full, waning gibbous, last quarter, waning crescent,
  33. // new, waxing crescent, first quarter, waxing gibbous.
  34. const uint8_t PHASE_LED_MASKS[8] = {
  35.   0b111111, 0b011111, 0b000111, 0b000001,
  36.   0b000000, 0b100000, 0b111000, 0b111110
  37. };
  38.  
  39. constexpr uint8_t MOON_WIDTH = 30;
  40. constexpr uint8_t MOON_HEIGHT = 30;
  41. constexpr uint8_t MOON_X = (128 - MOON_WIDTH) / 2;
  42. constexpr uint8_t MOON_Y = 18;
  43.  
  44. static const uint8_t PROGMEM full_moon_bits[] = {
  45. 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00,
  46. 0x80, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x01, 0xf0, 0xff, 0xff, 0x03,
  47. 0xf0, 0xff, 0xff, 0x03, 0xf8, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x0f,
  48. 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0x1f,
  49. 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f,
  50. 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f,
  51. 0xfe, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f,
  52. 0xfc, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x03,
  53. 0xf0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x01, 0x80, 0xff, 0x7f, 0x00,
  54. 0x00, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };
  55.  
  56. static const uint8_t PROGMEM waning_gibbous_bits[] = {
  57. 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0x00,
  58. 0xe0, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0x7f, 0x00,
  59. 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x1f, 0x00,
  60. 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x0f, 0x00,
  61. 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00,
  62. 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00,
  63. 0xff, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x0f, 0x00,
  64. 0xfe, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xf8, 0xff, 0x1f, 0x00,
  65. 0xf8, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0x00,
  66. 0x80, 0xff, 0xff, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x1f, 0x00 };
  67.  
  68. static const uint8_t PROGMEM last_quarter_bits[] = {
  69. 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x80, 0xff, 0x01, 0x00,
  70. 0xe0, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00,
  71. 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
  72. 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
  73. 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
  74. 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
  75. 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
  76. 0xfe, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00,
  77. 0xf8, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x01, 0x00,
  78. 0x80, 0xff, 0x01, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00 };
  79.  
  80. static const uint8_t PROGMEM crescent_old_bits[] = {
  81. 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
  82. 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
  83. 0xf8, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  84. 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
  85. 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
  86. 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
  87. 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  88. 0x7e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
  89. 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00,
  90. 0x80, 0x1f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00 };
  91.  
  92. static const uint8_t PROGMEM new_moon_bits[] = {
  93. 0x00, 0xf8, 0x07, 0x00, 0x00, 0x07, 0x38, 0x00, 0x80, 0x00, 0x40, 0x00,
  94. 0x60, 0x00, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x04,
  95. 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x10,
  96. 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x20,
  97. 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
  98. 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
  99. 0x01, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10,
  100. 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04,
  101. 0x08, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x02, 0x60, 0x00, 0x80, 0x01,
  102. 0x80, 0x00, 0x40, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0xf8, 0x07, 0x00 };
  103.  
  104. static const uint8_t PROGMEM crescent_new_bits[] = {
  105. 0x00, 0xf8, 0x07, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00,
  106. 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x07,
  107. 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x1f,
  108. 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x3f,
  109. 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f,
  110. 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f,
  111. 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x80, 0x1f,
  112. 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xe0, 0x07,
  113. 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xfc, 0x01,
  114. 0x00, 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00 };
  115.  
  116. static const uint8_t PROGMEM first_quarter_bits[] = {
  117. 0x00, 0xfc, 0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xe0, 0x7f, 0x00,
  118. 0x00, 0xe0, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x07,
  119. 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f,
  120. 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f,
  121. 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f,
  122. 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f,
  123. 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x1f,
  124. 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x07,
  125. 0x00, 0x80, 0xff, 0x07, 0x00, 0xc0, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x01,
  126. 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x07, 0x00 };
  127.  
  128. static const uint8_t PROGMEM waxing_gibbous_bits[] = {
  129. 0x00, 0xfc, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0x7f, 0x00,
  130. 0xc0, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0x07,
  131. 0x00, 0xff, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x1f,
  132. 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x3f,
  133. 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f,
  134. 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f,
  135. 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1f,
  136. 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x07,
  137. 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01,
  138. 0xc0, 0xff, 0x7f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0x07, 0x00 };
  139.  
  140. using MoonBitmap = const uint8_t *;
  141.  
  142. static const MoonBitmap moonBitmaps[8] = {
  143.   full_moon_bits,
  144.   waning_gibbous_bits,
  145.   last_quarter_bits,
  146.   crescent_old_bits,
  147.   new_moon_bits,
  148.   crescent_new_bits,
  149.   first_quarter_bits,
  150.   waxing_gibbous_bits
  151. };
  152.  
  153. static const char *const phaseNames[8] = {
  154.   "Full Moon",
  155.   "Waning Gibbous",
  156.   "Last Quarter",
  157.   "Old Crescent",
  158.   "New Moon",
  159.   "New Crescent",
  160.   "First Quarter",
  161.   "Waxing Gibbous"
  162. };
  163.  
  164. double julianDate(int year, int month, int day);
  165. uint8_t moonPhase(uint8_t &daysToFullMoon);
  166. void drawCentered(uint8_t baselineY, const char *text);
  167. void drawMoonScreen();
  168. void drawStatusScreen(const char *line1, const char *line2);
  169. void scanI2C();
  170. bool syncRtcFromWiFi();
  171. void setPhaseLeds(uint8_t phase);
  172.  
  173. void setup() {
  174.   Serial.begin(115200);
  175.   Wire.begin();
  176.   delay(250);
  177.  
  178.   for (uint8_t i = 0; i < MOON_LED_COUNT; ++i) {
  179.     pinMode(MOON_LED_PINS[i], OUTPUT);
  180.     digitalWrite(MOON_LED_PINS[i], LED_ACTIVE_HIGH ? LOW : HIGH);
  181.   }
  182.  
  183.   Serial.println("Moon phase display starting");
  184.   scanI2C();
  185.  
  186.   u8g2.begin();
  187.   u8g2.clearBuffer();
  188.   drawStatusScreen("OLED STARTED", "Checking RTC...");
  189.   u8g2.sendBuffer();
  190.   delay(1000);
  191.  
  192.   rtcReady = rtc.begin();
  193.  
  194.   if (!rtcReady) {
  195.     Serial.println("ERROR: DS3231 not found at I2C address 0x68");
  196.   } else {
  197.     Serial.println("DS3231 detected");
  198.  
  199.     const bool rtcLostPower = rtc.lostPower();
  200.     if (!syncRtcFromWiFi() && rtcLostPower) {
  201.       Serial.println("NTP unavailable; using sketch build time");
  202.       rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  203.     }
  204.   }
  205. }
  206.  
  207. void loop() {
  208.   u8g2.clearBuffer();
  209.   if (rtcReady) {
  210.     drawMoonScreen();
  211.   } else {
  212.     setPhaseLeds(4);  // New-moon mask: all phase LEDs off.
  213.     drawStatusScreen("RTC NOT FOUND", "Expected: 0x68");
  214.   }
  215.   u8g2.sendBuffer();
  216.   delay(1000);
  217. }
  218.  
  219. void drawStatusScreen(const char *line1, const char *line2) {
  220.   u8g2.setFont(u8g2_font_6x12_tf);
  221.   drawCentered(26, line1);
  222.   drawCentered(46, line2);
  223. }
  224.  
  225. void scanI2C() {
  226.   uint8_t found = 0;
  227.   Serial.println("I2C scan (RTC only; OLED is SPI):");
  228.  
  229.   for (uint8_t address = 1; address < 127; ++address) {
  230.     Wire.beginTransmission(address);
  231.     if (Wire.endTransmission() == 0) {
  232.       Serial.print("  found 0x");
  233.       if (address < 16) {
  234.         Serial.print('0');
  235.       }
  236.       Serial.println(address, HEX);
  237.       ++found;
  238.     }
  239.   }
  240.  
  241.   if (found == 0) {
  242.     Serial.println("  no I2C devices found");
  243.   }
  244. }
  245.  
  246. bool syncRtcFromWiFi() {
  247.   if (strcmp(WIFI_SSID, "YOUR_WIFI_NAME") == 0) {
  248.     Serial.println("Wi-Fi not configured; keeping DS3231 time");
  249.     return false;
  250.   }
  251.  
  252.   Serial.print("Connecting to Wi-Fi");
  253.   WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  254.  
  255.   const unsigned long connectStarted = millis();
  256.   while (WiFi.status() != WL_CONNECTED && millis() - connectStarted < 20000UL) {
  257.     Serial.print('.');
  258.     delay(500);
  259.   }
  260.   Serial.println();
  261.  
  262.   if (WiFi.status() != WL_CONNECTED) {
  263.     Serial.println("Wi-Fi connection timed out");
  264.     return false;
  265.   }
  266.  
  267.   Serial.println("Wi-Fi connected; requesting network time");
  268.   unsigned long epoch = 0;
  269.   const unsigned long timeStarted = millis();
  270.   while (epoch < 1700000000UL && millis() - timeStarted < 15000UL) {
  271.     epoch = WiFi.getTime();
  272.     if (epoch < 1700000000UL) {
  273.       delay(1000);
  274.     }
  275.   }
  276.  
  277.   WiFi.disconnect();
  278.  
  279.   if (epoch < 1700000000UL) {
  280.     Serial.println("Network time failed; keeping DS3231 time");
  281.     return false;
  282.   }
  283.  
  284.   rtc.adjust(DateTime(epoch));  // Store UTC in the DS3231.
  285.   Serial.print("DS3231 synchronized to Unix time ");
  286.   Serial.println(epoch);
  287.   return true;
  288. }
  289.  
  290. void setPhaseLeds(uint8_t phase) {
  291.   const uint8_t mask = PHASE_LED_MASKS[phase & 7];
  292.  
  293.   for (uint8_t i = 0; i < MOON_LED_COUNT; ++i) {
  294.     const bool on = mask & (1U << i);
  295.     digitalWrite(MOON_LED_PINS[i], on == LED_ACTIVE_HIGH ? HIGH : LOW);
  296.   }
  297. }
  298.  
  299. void drawMoonScreen() {
  300.   uint8_t daysToFullMoon = 0;
  301.   const uint8_t phase = moonPhase(daysToFullMoon);
  302.   setPhaseLeds(phase);
  303.  
  304.   // Small fixed-width title font. Its exact size is not relied on:
  305.   // drawCentered() measures the text before positioning it.
  306.   u8g2.setFont(u8g2_font_5x7_tf);
  307.   drawCentered(9, "Moon Phase Calculator");
  308.   u8g2.drawHLine(0, 12, 128);
  309.  
  310.   // The original 30x30 XBM moon images work with U8g2.
  311.   u8g2.drawXBMP(
  312.       MOON_X, MOON_Y, MOON_WIDTH, MOON_HEIGHT, moonBitmaps[phase]);
  313.  
  314.   // Show the phase name centered along the bottom.
  315.   u8g2.setFont(u8g2_font_6x12_tf);
  316.   drawCentered(63, phaseNames[phase]);
  317.  
  318.   // Keep the original small days-to-next-full-moon value at the right.
  319.   char daysText[4];
  320.   snprintf(daysText, sizeof(daysText), "%u", daysToFullMoon);
  321.   u8g2.setFont(u8g2_font_5x7_tf);
  322.   u8g2.drawStr(114, 28, daysText);
  323. }
  324.  
  325. void drawCentered(uint8_t baselineY, const char *text) {
  326.   const uint8_t width = u8g2.getStrWidth(text);
  327.   const int16_t x = (128 - width) / 2;
  328.   u8g2.drawStr(x > 0 ? x : 0, baselineY, text);
  329. }
  330.  
  331. uint8_t moonPhase(uint8_t &daysToFullMoon) {
  332.   const DateTime now = rtc.now();
  333.  
  334.   double cycle = julianDate(now.year(), now.month(), now.day());
  335.   cycle = int(cycle - 2244116.75);  // Original 1 Jan 1972 reference.
  336.   cycle /= 29.53;
  337.  
  338.   const long completedCycles = long(cycle);
  339.   const double cycleFraction = cycle - completedCycles;
  340.   const double elapsedDays = cycleFraction * 29.53;
  341.  
  342.   daysToFullMoon = uint8_t(29.53 - elapsedDays);
  343.  
  344.   // Round to the nearest of eight phase sectors and wrap 8 back to 0.
  345.   return (uint8_t(cycleFraction * 8.0 + 0.5)) & 7;
  346. }
  347.  
  348. double julianDate(int year, int month, int day) {
  349.   const int yy = year - int((12 - month) / 10);
  350.   int mm = month + 9;
  351.   if (mm >= 12) {
  352.     mm -= 12;
  353.   }
  354.  
  355.   const double k1 = 365.25 * (yy + 4172);
  356.   const double k2 = int((30.6001 * mm) + 0.5);
  357.   const double k3 = int(((((yy / 100) + 4) * 0.75) - 38));
  358.  
  359.   return k1 + k2 + day + 59 - k3;
  360. }
  361.  
Advertisement
Add Comment
Please, Sign In to add comment