Example #1
0
        public long hoursInDay()
        {
            int year  = getYear();
            int month = getMonth();
            int day   = getDay();

            TimeZone.Rule rule = tz().rule(year);
            if (TimeZone.isDstDate(rule, rule.dstStart, year, month, day))
            {
                return(23);
            }
            if (TimeZone.isDstDate(rule, rule.dstEnd, year, month, day))
            {
                return(25);
            }
            return(24);
        }
Example #2
0
        //////////////////////////////////////////////////////////////////////////
        // Formatting
        //////////////////////////////////////////////////////////////////////////

        public string format()
        {
            StringBuilder s   = new StringBuilder();
            int           len = pattern.Length;

            for (int i = 0; i < len; ++i)
            {
                // character
                int c = pattern[i];

                // literals
                if (c == '\'')
                {
                    while (true)
                    {
                        ++i;
                        if (i >= len)
                        {
                            throw ArgErr.make("Invalid pattern: unterminated literal").val;
                        }
                        c = pattern[i];
                        if (c == '\'')
                        {
                            break;
                        }
                        s.Append((char)c);
                    }
                    continue;
                }

                // character count
                int n = 1;
                while (i + 1 < len && pattern[i + 1] == c)
                {
                    ++i; ++n;
                }

                // switch
                bool invalidNum = false;
                switch (c)
                {
                case 'Y':
                    int y = this.year;
                    switch (n)
                    {
                    case 2:  y %= 100; if (y < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(y); break;

                    case 4:  s.Append(y); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'M':
                    if (mon == null)
                    {
                        throw ArgErr.make("Month not available").val;
                    }
                    switch (n)
                    {
                    case 4:
                        s.Append(mon.full(locale()));
                        break;

                    case 3:
                        s.Append(mon.abbr(locale()));
                        break;

                    case 2:  if (mon.ordinal() + 1 < 10L)
                        {
                            s.Append('0');
                        }
                        s.Append(mon.ordinal() + 1); break;

                    case 1:  s.Append(mon.ordinal() + 1); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'D':
                    switch (n)
                    {
                    case 3:  s.Append(day).Append(daySuffix(day)); break;

                    case 2:  if (day < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(day); break;

                    case 1:  s.Append(day); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'W':
                    if (weekday == null)
                    {
                        throw ArgErr.make("Weekday not available").val;
                    }
                    switch (n)
                    {
                    case 4:
                        s.Append(weekday.full(locale()));
                        break;

                    case 3:
                        s.Append(weekday.abbr(locale()));
                        break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'V':
                    int woy = weekOfYear();
                    if (woy < 1)
                    {
                        throw ArgErr.make("Week of year not available").val;
                    }
                    switch (n)
                    {
                    case 3:  s.Append(woy).Append(daySuffix(woy)); break;

                    case 2:  if (woy < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(woy); break;

                    case 1:  s.Append(woy); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'h':
                case 'k':
                    int h = this.hour;
                    if (c == 'k')
                    {
                        if (h == 0)
                        {
                            h = 12;
                        }
                        else if (h > 12)
                        {
                            h -= 12;
                        }
                    }
                    switch (n)
                    {
                    case 2:  if (h < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(h); break;

                    case 1:  s.Append(h); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'm':
                    switch (n)
                    {
                    case 2:  if (min < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(min); break;

                    case 1:  s.Append(min); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 's':
                    switch (n)
                    {
                    case 2:  if (sec < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(sec); break;

                    case 1:  s.Append(sec); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'S':
                    if (sec != 0 || ns != 0)
                    {
                        switch (n)
                        {
                        case 2:  if (sec < 10)
                            {
                                s.Append('0');
                            }
                            s.Append(sec); break;

                        case 1:  s.Append(sec); break;

                        default: invalidNum = true; break;
                        }
                    }
                    break;

                case 'a':
                    switch (n)
                    {
                    case 1:  s.Append(hour < 12 ? "a"  : "p"); break;

                    case 2:  s.Append(hour < 12 ? "am" : "pm"); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'A':
                    switch (n)
                    {
                    case 1:  s.Append(hour < 12 ? "A"  : "P"); break;

                    case 2:  s.Append(hour < 12 ? "AM" : "PM"); break;

                    default: invalidNum = true; break;
                    }
                    break;

                case 'f':
                case 'F':
                    int req = 0, opt = 0; // required, optional
                    if (c == 'F')
                    {
                        opt = n;
                    }
                    else
                    {
                        req = n;
                        while (i + 1 < len && pattern[i + 1] == 'F')
                        {
                            ++i; ++opt;
                        }
                    }
                    int frac = ns;
                    for (int x = 0, tenth = 100000000; x < 9; ++x)
                    {
                        if (req > 0)
                        {
                            req--;
                        }
                        else
                        {
                            if (frac == 0 || opt <= 0)
                            {
                                break;
                            }
                            opt--;
                        }
                        s.Append(frac / tenth);
                        frac  %= tenth;
                        tenth /= 10;
                    }
                    break;

                case 'z':
                    TimeZone.Rule rule = tz.rule(year);
                    switch (n)
                    {
                    case 1:
                        int offset = rule.offset;
                        if (dst)
                        {
                            offset += rule.dstOffset;
                        }
                        if (offset == 0)
                        {
                            s.Append('Z'); break;
                        }
                        if (offset < 0)
                        {
                            s.Append('-'); offset = -offset;
                        }
                        else
                        {
                            s.Append('+');
                        }
                        int zh = offset / 3600;
                        int zm = (offset % 3600) / 60;
                        if (zh < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(zh).Append(':');
                        if (zm < 10)
                        {
                            s.Append('0');
                        }
                        s.Append(zm);
                        break;

                    case 3:
                        s.Append(dst ? rule.dstAbbr : rule.stdAbbr);
                        break;

                    case 4:
                        s.Append(tz.name());
                        break;

                    default:
                        invalidNum = true;
                        break;
                    }
                    break;

                default:
                    if (FanInt.isAlpha(c))
                    {
                        throw ArgErr.make("Invalid pattern: unsupported char '" + (char)c + "'").val;
                    }

                    // check for symbol skip
                    if (i + 1 < len)
                    {
                        int next = pattern[i + 1];

                        // don't display symbol between ss.FFF if fractions is zero
                        if (next == 'F' && ns == 0)
                        {
                            break;
                        }

                        // don't display symbol between mm:SS if secs is zero
                        if (next == 'S' && sec == 0 && ns == 0)
                        {
                            break;
                        }
                    }

                    s.Append((char)c);
                    break;
                }

                // if invalid number of characters
                if (invalidNum)
                {
                    throw ArgErr.make("Invalid pattern: unsupported num of '" + (char)c + "' (x" + n + ")").val;
                }
            }

            return(s.ToString());
        }
Example #3
0
        //////////////////////////////////////////////////////////////////////////
        // Parse
        //////////////////////////////////////////////////////////////////////////

        internal DateTime parseDateTime(string s, TimeZone defTz, bool check)
        {
            try
            {
                // parse into fields
                tzOffset = System.Int32.MaxValue;
                parse(s);

                // now figure out what timezone to use
                TimeZone.Rule defRule = defTz.rule(year);
                if (tzName != null)
                {
                    // use defTz if tzName was specified and matches any variations of defTz
                    if (tzName == defTz.name() ||
                        tzName == defRule.stdAbbr ||
                        tzName == defRule.dstAbbr)
                    {
                        tz = defTz;
                    }

                    // try to map tzName to TimeZone, use defTz as fallback
                    else
                    {
                        tz = TimeZone.fromStr(tzName, false);
                        if (tz == null)
                        {
                            tz = defTz;
                        }
                    }
                }

                // if tzOffset was specified...
                else if (tzOffset != System.Int32.MaxValue)
                {
                    // figure out what expected offset was for defTz
                    int time      = hour * 3600 + min * 60 + sec;
                    int defOffset = defRule.offset + TimeZone.dstOffset(defRule, year, (int)mon.ordinal(), day, time);

                    // if specified offset matches expected offset for defTz then
                    // use defTz, otherwise use a vanilla GMT+/- timezone
                    if (tzOffset == defOffset)
                    {
                        tz = defTz;
                    }
                    else
                    {
                        tz = TimeZone.fromGmtOffset(tzOffset);
                    }
                }

                // no tzName or tzOffset specified, use defTz
                else
                {
                    tz = defTz;
                }

                // construct DateTime
                return(new DateTime(year, (int)mon.ordinal(), day, hour, min, sec, ns, tzOffset, tz));
            }
            catch (Exception) {}
            if (check)
            {
                throw ParseErr.make("DateTime", s).val;
            }
            return(null);
        }
Example #4
0
        private DateTime(long ticks, TimeZone tz)
        {
            // check boundary conditions 1901 to 2099
            if (ticks < minTicks || ticks >= maxTicks)
            {
                throw ArgErr.make("Ticks out of range 1901 to 2099").val;
            }

            // save ticks, time zone
            this.m_ticks = ticks;
            this.m_tz    = tz;

            // compute the year
            int year = ticksToYear(ticks);

            // get the time zone rule for this year, and
            // offset the working ticks by UTC offset
            TimeZone.Rule rule = m_tz.rule(year);
            ticks += rule.offset * nsPerSec;

            // compute the day and month; we may need to execute this
            // code block up to three times:
            //   1st: using standard time
            //   2nd: using daylight offset (if in dst)
            //   3rd: using standard time (if dst pushed us back into std)
            int  month, day, dstOffset = 0;
            long rem;

            while (true)
            {
                // recompute year based on working ticks
                year = ticksToYear(ticks);
                rem  = ticks - yearTicks[year - 1900];
                if (rem < 0)
                {
                    rem += nsPerYear;
                }

                // compute day of the year
                int dayOfYear = (int)(rem / nsPerDay);
                rem %= nsPerDay;

                // use lookup tables map day of year to month and day
                if (isLeapYear(year))
                {
                    month = monForDayOfYearLeap[dayOfYear];
                    day   = dayForDayOfYearLeap[dayOfYear];
                }
                else
                {
                    month = monForDayOfYear[dayOfYear];
                    day   = dayForDayOfYear[dayOfYear];
                }

                // if dstOffset is set to max, then this is
                // the third time thru the loop: std->dst->std
                if (dstOffset == System.Int32.MaxValue)
                {
                    dstOffset = 0; break;
                }

                // if dstOffset is non-zero we have run this
                // loop twice to recompute the date for dst
                if (dstOffset != 0)
                {
                    // if our dst rule is wall time based, then we need to
                    // recompute to see if dst wall time pushed us back
                    // into dst - if so then run through the loop a third
                    // time to get us back to standard time
                    if (rule.isWallTime() && TimeZone.dstOffset(rule, year, month, day, (int)(rem / nsPerSec)) == 0)
                    {
                        ticks    -= dstOffset * nsPerSec;
                        dstOffset = System.Int32.MaxValue;
                        continue;
                    }
                    break;
                }

                // first time in loop; check for daylight saving time,
                // and if dst is in effect then re-run this loop with
                // modified working ticks
                dstOffset = TimeZone.dstOffset(rule, year, month, day, (int)(rem / nsPerSec));
                if (dstOffset == 0)
                {
                    break;
                }
                ticks += dstOffset * nsPerSec;
            }

            // compute time of day
            int hour = (int)(rem / nsPerHour);  rem %= nsPerHour;
            int min  = (int)(rem / nsPerMin);   rem %= nsPerMin;

            // compute weekday
            int weekday = (firstWeekday(year, month) + day - 1) % 7;

            // fields
            int fields = 0;

            fields       |= ((year - 1900) & 0xff) << 0;
            fields       |= (month & 0xf) << 8;
            fields       |= (day & 0x1f) << 12;
            fields       |= (hour & 0x1f) << 17;
            fields       |= (min & 0x3f) << 22;
            fields       |= (weekday & 0x7) << 28;
            fields       |= (dstOffset != 0 ? 1 : 0) << 31;
            this.m_fields = fields;
        }
Example #5
0
        internal DateTime(int year, int month, int day,
                          int hour, int min, int sec,
                          long ns, int knownOffset, TimeZone tz)
        {
            if (year < 1901 || year > 2099)
            {
                throw ArgErr.make("year " + year).val;
            }
            if (month < 0 || month > 11)
            {
                throw ArgErr.make("month " + month).val;
            }
            if (day < 1 || day > numDaysInMonth(year, month))
            {
                throw ArgErr.make("day " + day).val;
            }
            if (hour < 0 || hour > 23)
            {
                throw ArgErr.make("hour " + hour).val;
            }
            if (min < 0 || min > 59)
            {
                throw ArgErr.make("min " + min).val;
            }
            if (sec < 0 || sec > 59)
            {
                throw ArgErr.make("sec " + sec).val;
            }
            if (ns < 0 || ns > 999999999L)
            {
                throw ArgErr.make("ns " + ns).val;
            }

            // compute ticks for UTC
            int  doy       = dayOfYear(year, month, day);
            int  timeInSec = hour * 3600 + min * 60 + sec;
            long ticks     = (long)yearTicks[year - 1900] +
                             (long)doy * nsPerDay +
                             (long)timeInSec * nsPerSec +
                             ns;

            // adjust for timezone and dst (we might know the UTC offset)
            TimeZone.Rule rule = tz.rule(year);
            bool          dst;

            if (knownOffset == System.Int32.MaxValue)
            {
                // don't know offset so compute from timezone rule
                ticks -= (long)rule.offset * nsPerSec;
                int dstOffset = TimeZone.dstOffset(rule, year, month, day, timeInSec);
                if (dstOffset != 0)
                {
                    ticks -= (long)dstOffset * nsPerSec;
                }
                dst = dstOffset != 0;
            }
            else
            {
                // we known offset, still need to use rule to compute if in dst
                ticks -= (long)knownOffset * nsPerSec;
                dst    = knownOffset != rule.offset;
            }

            // compute weekday
            int weekday = (firstWeekday(year, month) + day - 1) % 7;

            // fields
            int fields = 0;

            fields |= ((year - 1900) & 0xff) << 0;
            fields |= (month & 0xf) << 8;
            fields |= (day & 0x1f) << 12;
            fields |= (hour & 0x1f) << 17;
            fields |= (min & 0x3f) << 22;
            fields |= (weekday & 0x7) << 28;
            fields |= (dst ? 1 : 0) << 31;

            // commit
            this.m_ticks  = ticks;
            this.m_tz     = tz;
            this.m_fields = fields;
        }