private void init(DateTime dt, TimeZone timeZone) {
        this.tz = timeZone != null ? timeZone : dt.config().getOutputTimeZone();
        long millis = dt.toMillis();
        // Compensate for difference between the system time zone and the recorded time zone
        long duration = millis - GREG_EPOCH_UTC + timeZone.getOffset(dt.toMillis());
        this.nanosecond = dt.getNanos();
        this.weekday = calcWeekday(millis, timeZone);
        if (millis < GREG_EPOCH_UTC - this.tz.getRawOffset()) {
            initYeOlde(millis);
            return;
        }
        // Remove 400yr blocks, then 100yr, then 4, then 1.
        long quadCents = duration / QUADCENT;
        duration -= quadCents * QUADCENT;
        long cents = Math.min(3, duration / CENT);
        duration -= cents * CENT;
        long quadYears = duration / QUADYEAR;
        duration -= quadYears * QUADYEAR;
        year = Math.min(3, (int) (duration / YEAR));
        duration -= year * YEAR;
        // Calculate year based on those blocks
        year += 1600 + quadCents * 400 + cents * 100 + quadYears * 4;
        month = (int) (duration / (30 * DAY));
        if (MONTH[month] <= duration) {
            month++;
        }
        // Same strategy as above, removing largest chunks first.
        if (month > 0) {
            duration -= MONTH[month - 1];
        }
        day = (int) (duration / DAY);
        duration -= day * DAY;
        hour = (int) duration / HOUR;
        duration -= 1L * hour * HOUR;
        minute = (int) duration / 60000;
        duration -= minute * 60000L;
        second = (int) duration / 1000;
        day++;
        // Shift from March calendar start, to January calendar start.
        month += 2;
        if (month > 12) {
            year++;
            if (month == 15) {
                day = 29;
                month = 2;
            } else {
                month -= 12;
            }
        }

    }