📄 gregorian.java
字号:
/* * @(#)Gregorian.java 1.7 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */package sun.util.calendar;/** * Gregorian calendar calculations. The algorithms are from "Calendrical * Calculation" by Nachum Dershowitz and Edward M. Reingold (ISBN: * 0-521-56474-3). */public class Gregorian implements CalendarSystem { /** * The number of days between Gregorian January 1, 1 and January * 1, 1970. */ public static final int EPOCH_DATE = 719163; /** * Calculates Gregorian calendar fields from the given UTC value * which is the difference from Gregorian January 1, 1970 00:00:00 * GMT. * @param utc the UTC value in milliseconds * @return the CaledarDate object that contains the calculated Gregorian calendar field values. */ public static CalendarDate getCalendarDate(long utc) { long days; int millis; days = utc / ONE_DAY; millis = (int)(utc % ONE_DAY); if (millis < 0) { millis += ONE_DAY; days--; } days += EPOCH_DATE; CalendarDate cdate = getCalendarDateFromFixedDate(days); cdate.setTimeOfDay(millis); return cdate; } /** * Calculates milliseconds of given time from EPOCH, 1970-01-01 00:00AM. */ public static long dateToMillis(CalendarDate date) { long gd = getFixedDate(date.getYear(), date.getMonth(), date.getDate()); return ((gd - EPOCH_DATE) * ONE_DAY + date.getTimeOfDay()); } /** * Calculates milliseconds of given time from EPOCH, 1970-01-01 00:00AM. */ public static long dateToMillis(int year, int month, int day, int milliseconds) { long gd = getFixedDate(year, month, day); return ((gd - EPOCH_DATE) * ONE_DAY + milliseconds); } public static boolean validate(CalendarDate date) { int month = date.getMonth(); if (month < JANUARY || month > DECEMBER) { return false; } int days = getMonthLength(date.getYear(), month); if (date.getDate() <= 0 || date.getDate() > days) { return false; } return true; } private static final int[] days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /** * @param month 0-based */ public static int getMonthLength(int year, int month) { int days = days_in_month[month]; if (month == FEBRUARY && isLeapYear(year)) { days++; } return days; } /** * Returns number of days from 0001-01-01. Counting leap correction. */ public static final long getFixedDate(int year, int month, int day) { int prevyear = year - 1; month++; // 1-based month numbering long days ; if (prevyear >= 0) { days = (365 * (long)prevyear) + (prevyear / 4) - (prevyear / 100) + (prevyear / 400) + ((367 * month - 362) / 12) + day; } else { days = (365 * (long)prevyear) + floorDivide(prevyear, 4) - floorDivide(prevyear, 100) + floorDivide(prevyear, 400) + floorDivide((367 * month - 362), 12) + day; } if (month > 2) { days -= (isLeapYear(year)) ? 1 : 2; } return days; } /** * Calculates year/month/day from given date. The date is from 0001-01-01. */ public static CalendarDate getCalendarDateFromFixedDate(long fixedDate) { int year = getYear(fixedDate); int pday = (int)(fixedDate - getFixedDate(year, JANUARY, 1)); int corr = 2; long mar1 = getFixedDate(year, MARCH, 1); if (fixedDate < mar1) { corr = 0; } else if (fixedDate >= mar1 && isLeapYear(year)) { corr = 1; } int month = floorDivide((12 * (pday + corr) + 373), 367) - 1; int day = (int)(fixedDate - getFixedDate(year, month, 1) + 1); int dow = getDayOfWeekFromFixedDate(fixedDate); CalendarDate cdate = new CalendarDate(year, month, day); cdate.setDayOfWeek(dow); return cdate; } /** * Returns day of week of given day */ public static int getDayOfWeek(CalendarDate date) { long fixedDate = getFixedDate(date.getYear(), date.getMonth(), date.getDate()); return getDayOfWeekFromFixedDate(fixedDate); } private static final int getDayOfWeekFromFixedDate(long fixedDate) { if (fixedDate >= 0) { return (int)(fixedDate % 7) + SUNDAY; } return (int)mod(fixedDate, 7) + SUNDAY; } /** * Returns Gregorian year number of given date */ private static final int getYear(long fixedDate) { long d0; int d1, d2, d3; int n400, n100, n4, n1; int year; if (fixedDate >= 0) { d0 = fixedDate - 1; n400 = (int)(d0 / 146097); d1 = (int)(d0 % 146097); n100 = d1 / 36524; d2 = d1 % 36524; n4 = d2 / 1461; d3 = d2 % 1461; n1 = d3 / 365; } else { d0 = fixedDate - 1; n400 = (int)floorDivide(d0, 146097L); d1 = (int)mod(d0, 146097L); n100 = floorDivide(d1, 36524); d2 = mod(d1, 36524); n4 = floorDivide(d2, 1461); d3 = mod(d2, 1461); n1 = floorDivide(d3, 365); } year = 400 * n400 + 100 * n100 + 4 * n4 + n1; if (!(n100 == 4 || n1 == 4)) { ++year; } return year; } /** * @return true if the given year is a Gregorian leap year. */ public static final boolean isLeapYear(int year) { if (year >= 0) { return (((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0))); } return (((mod(year, 4) == 0) && ((mod(year, 100) != 0) || (mod(year, 400) == 0)))); } /** * Floor function working with negative number. * floor(3.14) = 3 and floor(-3.14) = -4. */ private static final long floorDivide(long n, long d) { return ((n >= 0) ? (n / d) : (((n + 1L) / d) - 1L)); } private static final int floorDivide(int n, int d) { return ((n >= 0) ? (n / d) : (((n + 1) / d) - 1)); } private static final long mod(long x, long y) { return (x - y * floorDivide(x, y)); } private static final int mod(int x, int y) { return (x - y * floorDivide(x, y)); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -