Home | History | Annotate | Download | only in jni
      1 #include "TimeUtils.h"
      2 #include <stdio.h>
      3 #include <cutils/tztime.h>
      4 
      5 namespace android {
      6 
      7 static void
      8 dump(const Time& t)
      9 {
     10     #ifdef HAVE_TM_GMTOFF
     11         long tm_gmtoff = t.t.tm_gmtoff;
     12     #else
     13         long tm_gmtoff = 0;
     14     #endif
     15     printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n",
     16             t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday,
     17             t.t.tm_hour, t.t.tm_min, t.t.tm_sec,
     18             t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday);
     19 }
     20 
     21 Time::Time()
     22 {
     23     t.tm_sec = 0;
     24     t.tm_min = 0;
     25     t.tm_hour = 0;
     26     t.tm_mday = 0;
     27     t.tm_mon = 0;
     28     t.tm_year = 0;
     29     t.tm_wday = 0;
     30     t.tm_yday = 0;
     31     t.tm_isdst = -1; // we don't know, so let the C library determine
     32     #ifdef HAVE_TM_GMTOFF
     33         t.tm_gmtoff = 0;
     34     #endif
     35 }
     36 
     37 
     38 #define COMPARE_FIELD(field) do { \
     39         int diff = a.t.field - b.t.field; \
     40         if (diff != 0) return diff; \
     41     } while(0)
     42 
     43 int
     44 Time::compare(Time& a, Time& b)
     45 {
     46     if (0 == strcmp(a.timezone, b.timezone)) {
     47         // if the timezones are the same, we can easily compare the two
     48         // times.  Otherwise, convert to milliseconds and compare that.
     49         // This requires that object be normalized.
     50         COMPARE_FIELD(tm_year);
     51         COMPARE_FIELD(tm_mon);
     52         COMPARE_FIELD(tm_mday);
     53         COMPARE_FIELD(tm_hour);
     54         COMPARE_FIELD(tm_min);
     55         COMPARE_FIELD(tm_sec);
     56         return 0;
     57     } else {
     58         int64_t am = a.toMillis(false /* use isDst */);
     59         int64_t bm = b.toMillis(false /* use isDst */);
     60         int64_t diff = am-bm;
     61         return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
     62     }
     63 }
     64 
     65 static const int DAYS_PER_MONTH[] = {
     66                         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
     67                     };
     68 
     69 static inline int days_this_month(int year, int month)
     70 {
     71     int n = DAYS_PER_MONTH[month];
     72     if (n != 28) {
     73         return n;
     74     } else {
     75         int y = year;
     76         return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28;
     77     }
     78 }
     79 
     80 void
     81 Time::switchTimezone(const char* timezone)
     82 {
     83     time_t seconds = mktime_tz(&(this->t), this->timezone);
     84     localtime_tz(&seconds, &(this->t), timezone);
     85 }
     86 
     87 String8
     88 Time::format(const char *format, const struct strftime_locale *locale) const
     89 {
     90     char buf[257];
     91     int n = strftime_tz(buf, 257, format, &(this->t), locale);
     92     if (n > 0) {
     93         return String8(buf);
     94     } else {
     95         return String8();
     96     }
     97 }
     98 
     99 static inline short
    100 tochar(int n)
    101 {
    102     return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
    103 }
    104 
    105 static inline short
    106 next_char(int *m, int k)
    107 {
    108     int n = *m / k;
    109     *m = *m % k;
    110     return tochar(n);
    111 }
    112 
    113 void
    114 Time::format2445(short* buf, bool hasTime) const
    115 {
    116     int n;
    117 
    118     n = t.tm_year+1900;
    119     buf[0] = next_char(&n, 1000);
    120     buf[1] = next_char(&n, 100);
    121     buf[2] = next_char(&n, 10);
    122     buf[3] = tochar(n);
    123 
    124     n = t.tm_mon+1;
    125     buf[4] = next_char(&n, 10);
    126     buf[5] = tochar(n);
    127 
    128     n = t.tm_mday;
    129     buf[6] = next_char(&n, 10);
    130     buf[7] = tochar(n);
    131 
    132     if (hasTime) {
    133       buf[8] = 'T';
    134 
    135       n = t.tm_hour;
    136       buf[9] = next_char(&n, 10);
    137       buf[10] = tochar(n);
    138 
    139       n = t.tm_min;
    140       buf[11] = next_char(&n, 10);
    141       buf[12] = tochar(n);
    142 
    143       n = t.tm_sec;
    144       buf[13] = next_char(&n, 10);
    145       buf[14] = tochar(n);
    146       bool inUtc = strcmp("UTC", timezone) == 0;
    147       if (inUtc) {
    148           buf[15] = 'Z';
    149       }
    150     }
    151 }
    152 
    153 String8
    154 Time::toString() const
    155 {
    156     String8 str;
    157     char* s = str.lockBuffer(150);
    158     #ifdef HAVE_TM_GMTOFF
    159         long tm_gmtoff = t.tm_gmtoff;
    160     #else
    161         long tm_gmtoff = 0;
    162     #endif
    163     sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)",
    164             t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min,
    165             t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst,
    166             (int)(((Time*)this)->toMillis(false /* use isDst */)/1000));
    167     str.unlockBuffer();
    168     return str;
    169 }
    170 
    171 void
    172 Time::setToNow()
    173 {
    174     time_t seconds;
    175     time(&seconds);
    176     localtime_tz(&seconds, &(this->t), this->timezone);
    177 }
    178 
    179 int64_t
    180 Time::toMillis(bool ignoreDst)
    181 {
    182     if (ignoreDst) {
    183         this->t.tm_isdst = -1;
    184     }
    185     int64_t r = mktime_tz(&(this->t), this->timezone);
    186     if (r == -1)
    187         return -1;
    188     return r * 1000;
    189 }
    190 
    191 void
    192 Time::set(int64_t millis)
    193 {
    194     time_t seconds = millis / 1000;
    195     localtime_tz(&seconds, &(this->t), this->timezone);
    196 }
    197 
    198 }; // namespace android
    199 
    200