Setting day of the week using DCF77 with RTC3231

Some time ago I created a digital clock project using an LCD display and an RTC module (The DS1307). I decided to upgrade it by adding a DCF77 receiver and a better RTC module (The DS3231).

Following this forum page I saw that someone had already managed to create a code that allowed updating the RTC module after receiving a "Time telegraph" from the DCF77 receiver.

However, this code does not use the weekday, which is what I used in my previous code

(Here is the code for my Arduino + DS1307 version. I had set a day of the week slideshow every 15 seconds.)

#define D5 5

#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);

char daysOfTheWeek[7][12] = {"Domenica.", "Lunedi.", "Martedi.", "Mercoledi.", "Giovedi.", "Venerdi!!!", "Sabato."}; //va da 1 a 7 e ritorna a 1. Domenica è 1.

void setup () 
{
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();//To Power ON the back light  
  pinMode (D5, OUTPUT);
  analogWrite(D5, 50);
  
  if (! rtc.begin()) 
  {
    lcd.print("Couldn't find RTC");
    while (1);
  }
if (! rtc.isrunning()) 
  {
    lcd.print("RTC is NOT running!");
  }
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));//auto update from computer time
    //rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));// to set the time manually 
}

void loop() {
  DateTime now = rtc.now();

//slide-show del giorno della settimana
    if((now.second()%15) == 0) {  
      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print("Oggi e':");  
      lcd.setCursor(4,1);
      lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);  
      delay(4000);                  
      lcd.clear();
    }
    
    else {   
    
//Mostra semplicemente la data e l'ora:     
      lcd.setCursor(0,0);  //prima colonna, prima riga.
      lcd.print("Ora:");

      if(now.hour() < 10) {
        lcd.setCursor(8,0);
        lcd.print("0");
        lcd.setCursor(9,0);
        lcd.print(now.hour());
      }
      else {
        lcd.setCursor(8,0);
        lcd.print(now.hour());
      }
      
      lcd.setCursor(10,0);
      lcd.print(':');

      if(now.minute() < 10) {
        lcd.setCursor(11,0);
        lcd.print("0");
        lcd.setCursor(12,0);
        lcd.print(now.minute());        
      }
      else {
        lcd.setCursor(11,0);
        lcd.print(now.minute());               
      }
      
      lcd.setCursor(13,0);
      lcd.print(':');

      if (now.second() < 10) {
        lcd.setCursor(14,0);
        lcd.print("0");
        lcd.setCursor(15,0);
        lcd.print(now.second());        
      }
      else {
        lcd.setCursor(14,0);
        lcd.print(now.second());
        }
      

      
      //DATA
      lcd.setCursor(0,1);
      lcd.print("Data:");

      if(now.day() < 10) {
        lcd.setCursor(6,1);
        lcd.print("0");
        lcd.setCursor(7,1);
        lcd.print(now.day());
      }
      else {
        lcd.setCursor(6,1);
        lcd.print(now.day());
      }
      
      lcd.setCursor(8,1);
      lcd.print('/');
      
      if(now.month() < 10) {
        lcd.setCursor(9,1);
        lcd.print("0");
        lcd.setCursor(10,1);
        lcd.print(now.month());
      }
      else {
        lcd.setCursor(9,1);
        lcd.print(now.month());
      }
      
      lcd.setCursor(11,1);
      lcd.print('/');
      
      lcd.setCursor(12,1);
      lcd.print(now.year());
      
      }
    } 

(Here, however, you can see how the creator of the code found online for the Arduino + DS3231 + DCF77receiver project does not foresee the use of the day of the week in two parts. The reference file is "jursDCFtime.h".)

First part:

void RTCreadTime(sTime &time)
// read current time from RTC
{
// Reset the register pointer
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  
  // A few of these need masks because certain bits are control bits
  time.bSecond= bcdToDec(Wire.read() & 0x7f);
  time.bMinute= bcdToDec(Wire.read());
  time.bHour  = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  bcdToDec(Wire.read()); // day of week not used
  time.bDay   = bcdToDec(Wire.read());
  time.bMonth = bcdToDec(Wire.read());
  time.iYear  = bcdToDec(Wire.read())+2000;  
}

Second part:

void RTCwriteTime(sTime time)
// write time to RTC
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(time.bSecond));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(time.bMinute));
  Wire.write(decToBcd(time.bHour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
  Wire.write(decToBcd(0)); // weekday not used
  Wire.write(decToBcd(time.bDay));
  Wire.write(decToBcd(time.bMonth));
  Wire.write(decToBcd(time.iYear-2000));
  Wire.endTransmission();  
}

Complete main code:

// DCF77 and RTC test sketch by 'jurs' for Arduino forum
// hardware required:
// RTC module: DS1307 or DS3231
// DCF77 module

#include <Wire.h>

// begin of user configuration area
#define DEBUGMODE 1  // 1 or 0 to show or not show debug messages
#define DCFPIN 2     // data pin of DCF77 module
#define DCF_INPUTMODE INPUT  // INPUT or INPUT_PULLUP
#define INVERTEDSIGNAL false  // false= normal signal, true= inverted signal
// end of user configuration area

#include "jursDCFtime.h"

void setup() {
  Serial.begin(9600);
  Serial.println(F("\nDCF77 and RTC test sketch by 'jurs'"));
  if (RTCinit()) Serial.println(F("RTC OK"));
  else Serial.println(F("RTC FAIL"));
  pinMode(DCFPIN, DCF_INPUTMODE);
}

unsigned long lastPrintTimeMillis;

void loop() {
  sTime time;
  if (dcfUpdate())
  {
    //(lastValidDCFtime);
    Serial.println("DCF77 TIME TELEGRAM RECEIVED!");
    
  }
  if (millis()-lastPrintTimeMillis>=1000) // each second
  { // read time from RTC and print it to Serial
    lastPrintTimeMillis+=1000;
    char buf[21];
    RTCreadTime(time);
    snprintf(buf,sizeof(buf),"%02d.%02d.%04d  %02d:%02d:%02d", time.bDay, time.bMonth, time.iYear, time.bHour, time.bMinute, time.bSecond);
    Serial.println(buf); // print date and time
  }
}

Full code of the file "jursDCFtime.h", required by the main code:

#include <Arduino.h>

// RTC functions
struct sTime // structure for holding a date and a time
{
  int  iYear;
  byte bMonth;
  byte bDay;
  byte bHour;
  byte bMinute;
  byte bSecond;
};

sTime dateTime; // global variable to hold a full date/time struct

byte daysInMonth(int year, byte month)
{
  if (month == 4 || month == 6 || month == 9 || month == 11)  
    return 30;  
  else if (month == 2)  
  {
    bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);  
    if (isLeapYear) return 29;
    else return 28;
  }  
  else return 31;
}

boolean validDate(int year, int month, int day)
{
  boolean valid=true;
  if (year<2000 || year>2199) valid=false;
  if (month<1 || month>12) valid=false;
  if (day<1 || day> daysInMonth(year, month)) valid=false;
  return valid;
}

boolean validTime(int hour, int minute, int second)
{
  boolean valid=true;
  if (hour<0 || hour>=24) valid=false;
  if (minute<0 || minute>=60) valid=false;
  if (second<0 || second>=60) valid=false;
  return valid;
}


void timeTask()
{
  static unsigned long lastUpdate;
  if (millis()-lastUpdate>=1000)
  {
    lastUpdate+=1000;
    dateTime.bSecond++;
    if (dateTime.bSecond>=60) {dateTime.bSecond=0; dateTime.bMinute++;}
    if (dateTime.bMinute>=60) {dateTime.bMinute=0; dateTime.bHour++;}
    if (dateTime.bHour>=24) {dateTime.bHour=0; dateTime.bDay++;}
    if (dateTime.bDay>daysInMonth(dateTime.iYear, dateTime.bMonth)) {dateTime.bDay=1; dateTime.bMonth++;}
    if (dateTime.bMonth>12) {dateTime.bMonth=1; dateTime.iYear++;}
  }
}

//###################################
// RTC routines for DS1307 and DS3231
//###################################

#include <Wire.h>
#define RTC_I2C_ADDRESS 0x68 // // I2C adress of DS1307 and DS3231 RTC


byte decToBcd(byte val) // RTC helper function
// Convert decimal number to binary coded decimal
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  // RTC helper function
// Convert binary coded decimal to decimal number
{
  return ( (val/16*10) + (val%16) );
}

boolean RTCinit()
{
  Wire.begin();
  delay(10); // small delay to stabilize I2C bus voltage
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  return (Wire.endTransmission()==0);
}

void RTCreadTime(sTime &time);

void RTCreadTime(sTime &time)
// read current time from RTC
{
// Reset the register pointer
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  
  // A few of these need masks because certain bits are control bits
  time.bSecond= bcdToDec(Wire.read() & 0x7f);
  time.bMinute= bcdToDec(Wire.read());
  time.bHour  = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  bcdToDec(Wire.read()); // day of week not used
  time.bDay   = bcdToDec(Wire.read());
  time.bMonth = bcdToDec(Wire.read());
  time.iYear  = bcdToDec(Wire.read())+2000;  
}

void RTCwriteTime(sTime time)
// write time to RTC
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(time.bSecond));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(time.bMinute));
  Wire.write(decToBcd(time.bHour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
  Wire.write(decToBcd(0)); // weekday not used
  Wire.write(decToBcd(time.bDay));
  Wire.write(decToBcd(time.bMonth));
  Wire.write(decToBcd(time.iYear-2000));
  Wire.endTransmission();  
}

// DCF77 functions

#define PULSE_ERRORLIMIT 40  // 40 ms seems to be a suitable value
#define PULSE_SHORTSECOND (1000-PULSE_ERRORLIMIT)
#define PULSE_LONGSECOND  (1000+PULSE_ERRORLIMIT)
#define PULSE_MINUTEMARK  (2000-PULSE_ERRORLIMIT)

// 8 Bytes = 64 Bits to store all 59 DCF bits in a minute
uint8_t dcfBits[8];  
byte dcfBitcount;

boolean parityOK(byte startbit, byte paritybit)
{ // test parity bit in the range startbit ... paritybit-1
  byte p=0;
  for (int i=startbit; i<=paritybit;i++) p+= bitRead(dcfBits[i/8],i%8);
  if (p%2 == 0) return true; // even parity detected
  else return false;
}

byte dcfDecodeBCD(byte startbit, byte numbits)
{ // return BCD encoded byte-value beginning at startbit
  byte b=0;
  for (int i=startbit;i<startbit+numbits;i++) bitWrite(b,i-startbit, bitRead(dcfBits[i/8],i%8));
  return b;
}

sTime lastValidDCFtime;

boolean dcfDecodeTime()
{
  int hour, minute, day, month, year;
  byte resultCode, parityError=0;
#if (DEBUGMODE==1)  
  // print bits of time code to serial
  for (int i=0;i<dcfBitcount;i++) Serial.print(bitRead(dcfBits[i/8],i%8));
  Serial.print('\t');Serial.println(dcfBitcount);
#endif  
  if(!parityOK(21,28)) bitSet(parityError,0); // parity error minute
  if(!parityOK(29,35)) bitSet(parityError,1); // parity error hour
  if(!parityOK(36,58)) bitSet(parityError,2); // parity error date
  hour   = 10*dcfDecodeBCD(33,2);  // tens of hours, 2 bit 
  hour  += dcfDecodeBCD(29,4);     // single hours, 4 bit 
  minute = 10*dcfDecodeBCD(25,3);  // tens of minutes, 3 bit
  minute += dcfDecodeBCD(21,4);    // single minutes, 4 bit

  day = 10*dcfDecodeBCD(40,2);     // day of month (tens), 2 bit
  day += dcfDecodeBCD(36,4);       // day of month (single), 4 bit
  month = 10*dcfDecodeBCD(49,1);   // tens of month, 1 bit
  month += dcfDecodeBCD(45,4);     // single digit of month, 4 bit
  year = 10*dcfDecodeBCD(54,4);    // tens of year, 4 bit
  year += dcfDecodeBCD(50,4);      // single digit of year, 4 bit
  if (dcfBitcount!=59)
  {
#if (DEBUGMODE==1)    
    Serial.println("Error: Time code must contain 59 bits!");
#endif        
  }
  else if (parityError)
  {
#if (DEBUGMODE==1)    
    Serial.println("Error: Wrong parity bit detected!");
#endif        
  }
  else
  {
    lastValidDCFtime.bHour=hour;
    lastValidDCFtime.bMinute=minute;
    lastValidDCFtime.bSecond=0;
    lastValidDCFtime.bDay=day;
    lastValidDCFtime.bMonth=month;
    lastValidDCFtime.iYear=2000+year;
#if (DEBUGMODE==1)    
    Serial.print(hour);Serial.print(':');
    Serial.print(minute);Serial.print(":00  ");
    Serial.print(day);Serial.print('/');
    Serial.print(month);Serial.print('/');
    Serial.println(year);
#endif            
    dcfBitcount=0;
    return true;
  }
  dcfBitcount=0;
  return false;
}


boolean dcfHandleBit(uint16_t hiTime, uint16_t pulseTime)
{
  if (dcfBitcount<60)
  {
    if (hiTime<150) bitClear(dcfBits[dcfBitcount/8],dcfBitcount%8);
    else  bitSet(dcfBits[dcfBitcount/8],dcfBitcount%8);
    dcfBitcount++;  
  }
  if (pulseTime>=PULSE_MINUTEMARK) return dcfDecodeTime();
  return false;
}

boolean dcfUpdate()
{
  static boolean lastState;
  static unsigned long lastChangeTime;
  static uint16_t hiMillis,loMillis;
  static byte cnt;
  
  boolean state= digitalRead(DCFPIN);
  if (INVERTEDSIGNAL) state=!state;
  if (state!=lastState)
  {
    long timeDiff=millis()-lastChangeTime;
    lastState=state;
    lastChangeTime+= timeDiff;
    if (state)
    {
      cnt++;
      loMillis+= timeDiff;
      uint16_t pulsetime=hiMillis+loMillis;
      if ((pulsetime>=PULSE_SHORTSECOND && pulsetime<=PULSE_LONGSECOND)|| pulsetime>=PULSE_MINUTEMARK) 
      {
#if (DEBUGMODE==1)
        Serial.print(cnt);Serial.print('\t');
        Serial.print(hiMillis);Serial.print('\t');
        Serial.print(loMillis);Serial.print('\t');
        Serial.print(pulsetime);Serial.print('\t');
        Serial.println();
#endif        
        boolean result=dcfHandleBit(hiMillis, pulsetime);
        hiMillis=0;
        loMillis=0;
        cnt=0;
        return result;
      }
    }
    else hiMillis+= timeDiff;
  }
  return false;
}

I was thinking of using the RTCLib library since it has a function that could calculate the day of the week and try to somehow control the slideshow with the lastPrintTimeMillis parameter. However, this solution seems cumbersome to me and I was therefore thinking of correcting the "jursDCFtime.h" file, but I didn't know how to do it.

Can you help me? Thank you in advance for your attention.

You could add it yourself. Perhaps you can try something like the following.

In jursDCFtime.h, add a field to sTime,

struct sTime {
  // ...
  byte bDayOfWeek;
};

and near the end of dcfDecodeTime() in the last else clause, you could add the following line.

  lastValidDCFtime.bDayOfWeek = dcfDecodeBCD(42, 3);  // See [1].

[1] DCF77 - Wikipedia

Thanks for reminding us that the time signal does have a day-of-the-week included.

a7

Oh, so no need to use any library nor the RTC for the day of the week it seems... Right?

Problem is, even if I add correctly that field, how do I write that 3 bits to the RTC?

You could read the date and time stuff from the RTC, then write it all back again but change the day of week value before you do.

There should be two methods in the library. I look when I can,

Or you could just own the RTC and write directly into the appropriate register. The data sheet shows where all the time information goes into the internal registers of the chip.

void pokeRTC(unsigned char regAddress, unsigned char value)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(regAddress);

  Wire.write(value);
  Wire.endTransmission();
}

Day of week is at address… I'll look when I am not moving.

a7

OK, so get the DateTime

  DateTime now = rtc.now();

Then use the values from that variable instead of the constants in adjust()

    rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));// to set the time manually

HTH

a7

If you look at the code for the RTClib library, it does not use the day of the week from the RTC. For the DS1307 it always writes 0 to the RTC for day of the week, for the DS3231 it write the day of the week number (which is calculated, RTClib never stores the day of the week), but ignores it when reading the time back from the RTC.

The day of the week is between the hour and day registers, here is it written as 0, but the actual value should be 1 to 7. It is up to you as to which actual day 1 represents, the DS3231 does not care.

Right. It is at address 0x3 in the register file, so

  pokeRTC(0x3, 6);

would make it day 6 from 1 through 7. As mentioned, there is no official association with 1 being Sunday, totally up to you to decide.

a7

Ok, this afternoon, thanks to your advices, I got my hands dirty.

Here's what I did:

@david_2018 @alto777

  1. Added the element "bWday" in the struct at the beginning of "jursDCFtime"
struct sTime // structure for holding a date and a time
{
  int  iYear;
  byte bMonth;
  byte bDay;
  byte bHour;
  byte bMinute;
  byte bSecond;
  byte bWday;
};
  1. Added the time.bWday = bcdToDec(Wire.read()); // day of week line in the RTCreadTime function:
void RTCreadTime(sTime &time)
// read current time from RTC
{
// Reset the register pointer
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  
  // A few of these need masks because certain bits are control bits
  time.bSecond= bcdToDec(Wire.read() & 0x7f);
  time.bMinute= bcdToDec(Wire.read());
  time.bHour  = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  
  time.bWday = bcdToDec(Wire.read()); // day of week
  
  time.bDay   = bcdToDec(Wire.read());
  time.bMonth = bcdToDec(Wire.read());
  time.iYear  = bcdToDec(Wire.read())+2000;  
}i

(without using any bit mask... I've seen the datasheet of the DS3231 and seems like at add 03h (why the h ??) there are no control bits... or maybe the mask bits are related to the I2S protocol?)

While, in the DCF decoding part:

  1. Added the line lastValidDCFtime.bWday = dcfDecodeBCD(42, 3); as suggested from @jfjlaros
boolean dcfDecodeTime()
{
  int hour, minute, day, month, year, Wday;
  byte resultCode, parityError=0;
#if (DEBUGMODE==1)  
  // print bits of time code to serial
  for (int i=0;i<dcfBitcount;i++) Serial.print(bitRead(dcfBits[i/8],i%8));
  Serial.print('\t');Serial.println(dcfBitcount);
#endif  
  if(!parityOK(21,28)) bitSet(parityError,0); // parity error minute
  if(!parityOK(29,35)) bitSet(parityError,1); // parity error hour
  if(!parityOK(36,58)) bitSet(parityError,2); // parity error date
  hour   = 10*dcfDecodeBCD(33,2);  // tens of hours, 2 bit 
  hour  += dcfDecodeBCD(29,4);     // single hours, 4 bit 
  minute = 10*dcfDecodeBCD(25,3);  // tens of minutes, 3 bit
  minute += dcfDecodeBCD(21,4);    // single minutes, 4 bit

  day = 10*dcfDecodeBCD(40,2);     // day of month (tens), 2 bit
  day += dcfDecodeBCD(36,4);       // day of month (single), 4 bit
  month = 10*dcfDecodeBCD(49,1);   // tens of month, 1 bit
  month += dcfDecodeBCD(45,4);     // single digit of month, 4 bit
  year = 10*dcfDecodeBCD(54,4);    // tens of year, 4 bit
  year += dcfDecodeBCD(50,4);      // single digit of year, 4 bit
  if (dcfBitcount!=59)
  {
#if (DEBUGMODE==1)    
    Serial.println("Error: Time code must contain 59 bits!");
#endif        
  }
  else if (parityError)
  {
#if (DEBUGMODE==1)    
    Serial.println("Error: Wrong parity bit detected!");
#endif        
  }
  else
  {
    lastValidDCFtime.bHour=hour;
    lastValidDCFtime.bMinute=minute;
    lastValidDCFtime.bSecond=0;
    lastValidDCFtime.bDay=day;
 

//##############################   
// ## ADDED HERE!
    lastValidDCFtime.bWday = dcfDecodeBCD(42, 3);
// ## ADDED HERE!
//##############################


    lastValidDCFtime.bMonth=month;
    lastValidDCFtime.iYear=2000+year;
#if (DEBUGMODE==1)    
    Serial.print(hour);Serial.print(':');
    Serial.print(minute);Serial.print(":00  ");
    Serial.print(day);Serial.print('/');
    Serial.print(month);Serial.print('/');
    Serial.println(year);
#endif            
    dcfBitcount=0;
    return true;
  }
  dcfBitcount=0;
  return false;
}

All was compiled and no error came up. Do you think I did right?

A little update: I'm getting a strange data output whenever i write the correcct time telegram to the RTC. Maybe is a writing to the RTC error.

I did some digging around, and I found this for you.
(I just modified it to use byte rather than int for m and d.)

byte weekday(int y, byte m, byte d) {
  if ((y<1583) || (y>9999)) return 0;
  if (d<1) return 0;
  int l = ((y%(((y%100)==0)?400:4)==0)?1:0);
  int n = y + (y/4) - (y/100) + (y/400);
  switch (m) {
    case 1:  if (d>31) return 0;  n+=(1-l); break;
    case 2: if (d>28+l) return 0; n+=(4-l); break;
    case 3:  if (d>31) return 0;  n+= 4;    break;
    case 4:  if (d>30) return 0;  break;
    case 5:  if (d>31) return 0;  n+= 2; break;
    case 6:  if (d>30) return 0;  n+= 5; break;
    case 7:  if (d>31) return 0;  break;
    case 8:  if (d>31) return 0;  n+= 3; break;
    case 9:  if (d>30) return 0;  n+= 6; break;
    case 10: if (d>31) return 0;  n+= 1; break;
    case 11: if (d>30) return 0;  n+= 4; break;
    case 12: if (d>31) return 0;  n+= 6; break;
    default: return 0;
  }
  n += d;
  n = ((n+4)%7)+1;
  return n;  // 1 for Mon, 2 for Tue, ..., 7 for Sun
}

A little more compact version of DOW for Monday = 1:

byte t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};    


if ( m < 3 ) y -= 1;
byte DOW = (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;

Also, you don't have to mess with the BCD stuff for DOW. The highest value is 7, which fits in the first nibble no matter how you represent it. So it can just be byte.

You end up modifying the value of y if the month is January or February. Maybe you care, maybe you don't.