# Thread: libmusl time: Help understanding how __year_to_secs works

1. ## libmusl time: Help understanding how __year_to_secs works

Hey guys!

Looking to implement some functions that relate to time within a project I am working on and decided to look at what other devs have done to handle time within C. I decided to look into the C standard libraries, in particular muslc (I've read that this is a good standard library) in hopes to guide my work and to learn more about how it is implemented.

I have encounted a function that is beyond my comprehension by just reading the source alone. There is no documentation I can find on it, however I am new to poking around large libraries like this, so I am not entirely sure where to look either. The function in question is as follows:

Code:
```long long __year_to_secs(long long year, int *is_leap)
{
if (year-2ULL <= 136) {
int y = year;
int leaps = (y-68)>>2;
if (!((y-68)&3)) {
leaps--;
if (is_leap) *is_leap = 1;
} else if (is_leap) *is_leap = 0;
return 31536000*(y-70) + 86400*leaps;
}

int cycles, centuries, leaps, rem;

if (!is_leap) is_leap = &(int){0};
cycles = (year-100) / 400;
rem = (year-100) % 400;
if (rem < 0) {
cycles--;
rem += 400;
}
if (!rem) {
*is_leap = 1;
centuries = 0;
leaps = 0;
} else {
if (rem >= 200) {
if (rem >= 300) centuries = 3, rem -= 300;
else centuries = 2, rem -= 200;
} else {
if (rem >= 100) centuries = 1, rem -= 100;
else centuries = 0;
}
if (!rem) {
*is_leap = 0;
leaps = 0;
} else {
leaps = rem / 4U;
rem %= 4U;
*is_leap = !rem;
}
}

leaps += 97*cycles + 24*centuries - *is_leap;

return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
}```
I am posting this here to hopefully get some insight into understanding this code (concepts and algorithms used), and perhaps be pointed to some resources that might be available to me to aid in understanding it (documentation I may be missing?).

2. First of all, wherever you got this "Library", it is NOT a "Standard Library".

Standard libraries, are the libraries provided with the compiler. The Operating System may, and usually does contain other libraries as part of the O/S. They would be well documented if designed to be used by a programmer.

Where did you obtain this "library"? What was the file you downloaded?

3. musl libc

musl is a C standard library implementation for Linux.
Tim S.

4. Originally Posted by stahta01
musl libc

Tim S.
I was not familiar with that library. Thanks!

iamsoydev:

The library is well documented at the link Tim provided.

5. What an interesting thechnique:

Code:
`if ( ! is_leap ) is_leap = &(int){0};`

6. Originally Posted by flp1969
What an interesting thechnique:

Code:
`if ( ! is_leap ) is_leap = &(int){0};`
Yeah, interesting. That caught my eye, too.

7. Start by wrapping a small test program around it.
Code:
```int main ( ) {
for ( int year = 0 ; year <= 2100 ; year++ ) {
int leap = 42;
long long seconds = __year_to_secs(year, &leap);
printf("year=%d seconds=%lld, leap=%d\n", year, seconds, leap);
}
}

\$ gcc -Wall -Wextra -g foo.c
\$ ./a.out
year=65 seconds=-157766400, leap=0
year=66 seconds=-126230400, leap=0
year=67 seconds=-94694400, leap=0
year=68 seconds=-63158400, leap=1
year=69 seconds=-31536000, leap=0
year=70 seconds=0, leap=0
year=71 seconds=31536000, leap=0
year=72 seconds=63072000, leap=1
year=73 seconds=94694400, leap=0
year=74 seconds=126230400, leap=0
year=75 seconds=157766400, leap=0
...
year=1900 seconds=57749241600, leap=0
year=1901 seconds=57780777600, leap=0
year=1902 seconds=57812313600, leap=0
year=1903 seconds=57843849600, leap=0
year=1904 seconds=57875385600, leap=1
year=1905 seconds=57907008000, leap=0
year=1906 seconds=57938544000, leap=0
year=1907 seconds=57970080000, leap=0
year=1908 seconds=58001616000, leap=1
year=1909 seconds=58033238400, leap=0
year=1910 seconds=58064774400, leap=0
...```
Year 70 seems an odd place to start counting from.

> __year_to_secs
Names beginning with double underscores are reserved identifiers.
Originally Posted by c99
7.1.3 Reserved identifiers
— All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
— All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
The simple calculation ignores all the calendar meddling through centuries past.
Gregorian calendar - Wikipedia

8. Originally Posted by Salem
Year 70 seems an odd place to start counting from.
In the tm structure, the tm_year field is the year minus 1900, so a value of 70 is 1970, which is the Unix epoch. Not so odd after all (well, I guess you could say the Unix epoch of 1970 was an odd choice, but at least it explains why this function starts years at 70).