cancel
Showing results for 
Search instead for 
Did you mean: 

Year 2038 Problem

Brian12412
Associate II

Does STM currently have a guideline or recommendation(s) for handling the 2038 problem?

1 ACCEPTED SOLUTION

Accepted Solutions

STM32 RTCs store year as last 2 digits. They also have a primitive leap-year calculation that only checks remainder of 4.
So the year will go from 0 to 99 and then wrap (overflow). So a fixed offset of 2000 means the year will fail at 2100.
Also leap years will fail in 2100 as 2100 is seen as a leap year, when it's not.

So they have two year-2100 problems.

I have a fix for both:

  1. Use build year to calculate current year. Will work from build year to buildyear + 99, then it will overflow to buildyear. So the program will fail in 100 years (in 2125) instead of 75 years (2100).
  2. if year in RTC is 00 and date is 29 feb, then jump to march 1st. This fixes leap years until 2399 since 2100, 2200 and 2300 are not leap years. Will fail in 2400 instead of 2100.

run this before processing rtc dates:

 

 

 

 

HAL_RTC_GetTime(&hrtc, &systemTimeTemp, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &systemDateTemp, RTC_FORMAT_BIN); // Always call GetDate after GetTime (RTC locking)

//leap year correction to allow proper leap year until 2400
if (systemDateTemp.Year == 0 && systemDateTemp.Month == 2 && systemDateTemp.Date == 29)
{
	//skip leap year as year is multiple of 100, but not multiple of 400
	systemDateTemp.Month = 3;
	systemDateTemp.Date = 1;

	__disable_irq();
	SystemTime = systemTimeTemp;
	SystemDate = systemDateTemp;
	__enable_irq();

	HAL_RTC_SetTime(&hrtc, &SystemTime, RTC_FORMAT_BIN);
	HAL_RTC_SetDate(&hrtc, &SystemDate, RTC_FORMAT_BIN);
}
else
{
	__disable_irq();
	SystemTime = systemTimeTemp;
	SystemDate = systemDateTemp;
	__enable_irq();
}

 

 

 

 

Use this to convert rtc year to absolute year:

 

 

 

 

#define DATE_TO_YEAR(d) (d[7] == '?' ? 1900 : \
                         (((d[7] - '0') * 1000 ) + (d[8] - '0') * 100 + (d[9] - '0') * 10 + d[10] -'0'))

#define BUILD_YEAR DATE_TO_YEAR(__DATE__)

// allow operation beyond 2099 (up to BUILD_YEAR + 99)
uint16_t yearAbs = systemDateCopy.Year + (BUILD_YEAR/100)*100;
if (yearAbs < BUILD_YEAR)
{
  yearAbs += 100;
}

 

 

 

If you want the program to work longer you need to periodically update the firmware to update the build date. Or you store the year in eeprom every year. RTC battery will fail before 2100. But you can always replace the battery and set the time again. It would be nice if products made now won't be automatically obsolete in 2100.

 

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

View solution in original post

7 REPLIES 7
tjaekel
Lead

What is it?

You mean the year 2038 problem - as @repaint suggested ?

Where do you see that being a specific issue for the STM32 ?

AScha.3
Chief III

You ask about a problem with systems which measure Unix time .

But here is not a Unix system, but just a controller with RTC , that has only years 10 + 1 in BCD : 2025 is only "25" in RTC :

AScha3_0-1740742377026.png

So its up to you, how you handle the full date in your software :

if using a uint_16t to store the "full" year, you will get a problem in the year 65536 - if your device still running and in use.  How long you expect it working and be in use ?

If you feel a post has answered your question, please click "Accept as Solution".

Depends a lot on the robustness of  design. Many RTC and calendars assume 2100 is a leap year.

Seen too many with a 1901 to 2099 limit, not that it's likely to be an issue, but people get lazy, and fewer are maintaining and understanding systems.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

STM32 RTCs store year as last 2 digits. They also have a primitive leap-year calculation that only checks remainder of 4.
So the year will go from 0 to 99 and then wrap (overflow). So a fixed offset of 2000 means the year will fail at 2100.
Also leap years will fail in 2100 as 2100 is seen as a leap year, when it's not.

So they have two year-2100 problems.

I have a fix for both:

  1. Use build year to calculate current year. Will work from build year to buildyear + 99, then it will overflow to buildyear. So the program will fail in 100 years (in 2125) instead of 75 years (2100).
  2. if year in RTC is 00 and date is 29 feb, then jump to march 1st. This fixes leap years until 2399 since 2100, 2200 and 2300 are not leap years. Will fail in 2400 instead of 2100.

run this before processing rtc dates:

 

 

 

 

HAL_RTC_GetTime(&hrtc, &systemTimeTemp, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &systemDateTemp, RTC_FORMAT_BIN); // Always call GetDate after GetTime (RTC locking)

//leap year correction to allow proper leap year until 2400
if (systemDateTemp.Year == 0 && systemDateTemp.Month == 2 && systemDateTemp.Date == 29)
{
	//skip leap year as year is multiple of 100, but not multiple of 400
	systemDateTemp.Month = 3;
	systemDateTemp.Date = 1;

	__disable_irq();
	SystemTime = systemTimeTemp;
	SystemDate = systemDateTemp;
	__enable_irq();

	HAL_RTC_SetTime(&hrtc, &SystemTime, RTC_FORMAT_BIN);
	HAL_RTC_SetDate(&hrtc, &SystemDate, RTC_FORMAT_BIN);
}
else
{
	__disable_irq();
	SystemTime = systemTimeTemp;
	SystemDate = systemDateTemp;
	__enable_irq();
}

 

 

 

 

Use this to convert rtc year to absolute year:

 

 

 

 

#define DATE_TO_YEAR(d) (d[7] == '?' ? 1900 : \
                         (((d[7] - '0') * 1000 ) + (d[8] - '0') * 100 + (d[9] - '0') * 10 + d[10] -'0'))

#define BUILD_YEAR DATE_TO_YEAR(__DATE__)

// allow operation beyond 2099 (up to BUILD_YEAR + 99)
uint16_t yearAbs = systemDateCopy.Year + (BUILD_YEAR/100)*100;
if (yearAbs < BUILD_YEAR)
{
  yearAbs += 100;
}

 

 

 

If you want the program to work longer you need to periodically update the firmware to update the build date. Or you store the year in eeprom every year. RTC battery will fail before 2100. But you can always replace the battery and set the time again. It would be nice if products made now won't be automatically obsolete in 2100.

 

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.
Brian12412
Associate II

Thank you for the responses.  A lot of useful information that answers my original question.  I thought perhaps STM would have some core guidelines for this sort thing and therefore wanted to ask about it.