summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/gmtime.c
blob: deb24e08c92f30612e1ada2562baf914cb0ee93a (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
#include <time.h>

/* seconds per day */
#define SPD 24*60*60

/* days per month -- nonleap! */
const short __spm[13] =
  { 0,
    (31),
    (31+28),
    (31+28+31),
    (31+28+31+30),
    (31+28+31+30+31),
    (31+28+31+30+31+30),
    (31+28+31+30+31+30+31),
    (31+28+31+30+31+30+31+31),
    (31+28+31+30+31+30+31+31+30),
    (31+28+31+30+31+30+31+31+30+31),
    (31+28+31+30+31+30+31+31+30+31+30),
    (31+28+31+30+31+30+31+31+30+31+30+31),
  };

static inline int isleap(int year) {
  /* every fourth year is a leap year except for century years that are
   * not divisible by 400. */
/*  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */
  return (!(year%4) && ((year%100) || !(year%400)));
}

struct tm *gmtime(const time_t *timep) {
  static struct tm r;
  time_t i;
  register time_t work=*timep%(SPD);
  r.tm_sec=work%60; work/=60;
  r.tm_min=work%60; r.tm_hour=work/60;
  work=*timep/(SPD);
  r.tm_wday=(4+work)%7;
  for (i=1970; ; ++i) {
    register time_t k=isleap(i)?366:365;
    if (work>=k)
      work-=k;
    else
      break;
  }
  r.tm_year=i-1900;
  r.tm_yday=work;

  r.tm_mday=1;
  if (isleap(i) && (work>58)) {
    if (work==59) r.tm_mday=2; /* 29.2. */
    work-=1;
  }

  for (i=11; i && (__spm[i]>work); --i) ;
  r.tm_mon=i;
  r.tm_mday+=work-__spm[i];
  return &r;
}