summaryrefslogtreecommitdiff
path: root/libc/time/tm_conv.c
blob: 96f4735b16982bfc2e4b5f0c791f1ee457e87795 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#include <time.h>

/* This is a translation from ALGOL in Collected Algorithms of CACM. */
/* Copied from Algorithm 199, Author: Robert G. Tantzen */

void
__tm_conv(tmbuf, timep, offset)
struct tm *tmbuf;
time_t *timep;
time_t offset;
{
static int   moffset[] =
   {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

   long s;
   long  j, d, m, y;

   offset += *timep;

   tmbuf->tm_isdst = 0;		/* Someone else can set this */

   j = offset / 86400L + 719469;
   s = offset % 86400L;

   if( s < 0 ) { s += 86400L; j--; }

   tmbuf->tm_sec = s % 60;
   tmbuf->tm_min = (s / 60) % 60;
   tmbuf->tm_hour = s / 3600;

   tmbuf->tm_wday = (j+2) % 7;

   /*
    * Julian date converter. Takes a julian date (the number of days since
    * some distant epoch or other), and fills tmbuf.
    */

   y = (4L * j - 1L) / 146097L;
   j = 4L * j - 1L - 146097L * y;
   d = j / 4L;
   j = (4L * d + 3L) / 1461L;
   d = 4L * d + 3L - 1461L * j;
   d = (d + 4L) / 4L;
   m = (5L * d - 3L) / 153L;
   d = 5L * d - 3 - 153L * m;
   d = (d + 5L) / 5L;
   y = 100L * y + j;
   if (m < 10)
      m += 2;
   else
   {
      m -= 10;
      ++y;
   }

   tmbuf->tm_year = y - 1900;
   tmbuf->tm_mon = m;
   tmbuf->tm_mday = d;

   tmbuf->tm_yday = d + moffset[m];
   if (m > 1 && ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)))
      tmbuf->tm_yday++;
}