Да, это возможно.
Существуют астрономические алгоритмы, которые позволяют выполнять числовой перевод между номером дня по юлианскому календарю и отметкой даты и времени. Алгоритм, с которым я знаком, был опубликован Дж. Миусом в его Астрономических алгоритмах, 2-е издание. Этот алгоритм преобразует число дней по юлианскому календарю в вектор целых чисел, представляющих соответствующие:
- ГОД
- MONTH_IN_YEAR (1–12)
- DAY_IN_MONTH (1–28,29,30,31 соответственно)
- HOUR_IN_DAY (0–23)
- MINUTE_IN_HOUR (0–59)
- SECOND_IN_MINUTE (0–59)
- MILLISECOND_IN_SECOND (0–999)
Поскольку и время POSIX, и числа дней по юлианскому календарю являются последовательностями дат (количество последовательных единиц времени), их взаимное преобразование тривиально. Таким образом, первым шагом для использования этого алгоритма будет преобразование времени POSIX (миллис с полуночи 1 января 1970 г.) в число дней по юлианскому календарю (количество дней с 24 ноября 4714 г. до н.э. в пролептическом григорианском календаре). Это тривиально, так как вы просто конвертируете миллисекунды в дни и настраиваете эпоху.
Вот константы:
/** Accessor index for year field from a date/time vector of ints. */
public static final int YEAR = 0;
/** Accessor index for month-in-year field from a date/time vector of ints */
public static final int MONTH = 1;
/** Accessor index for day-in-month field from a date/time vector of ints */
public static final int DAY = 2;
/** Accessor index for hour-in-day field from a date/time vector of ints */
public static final int HOURS = 3;
/** Accessor index for minute-in-hour field from a date/time vector of ints */
public static final int MINUTES = 4;
/** Accessor index for second-in-minute field from a date/time vector of ints */
public static final int SECONDS = 5;
/** Accessor index for millis-in-second field from a date/time vector of ints */
public static final int MILLIS = 6;
/** The POSIX Epoch represented as a modified Julian Day number */
public static final double POSIX_EPOCH_AS_MJD = 40587.0d;
А вот метод для алгоритма, который преобразует номер дня по юлианскому календарю (поставляется как double
) в вектор целых чисел. В приведенном ниже коде вы можете заменить функцию trunc()
на Math.floor()
и сохранить правильное поведение:
public static int[] toVectorFromDayNumber(double julianDay) {
int[] ymd_hmsm = {YEAR, MONTH, DAY, HOURS, MINUTES, SECONDS, MILLIS};
int a, b, c, d, e, z;
double f, x;
double jd = julianDay + 0.5;
z = (int) trunc(jd);
f = (jd - z) + (0.5 / (86400.0 * 1000.0));
if (z >= 2299161) {
int alpha = (int) trunc((z - 1867216.25) / 36524.25);
a = z + 1 + alpha - (alpha / 4);
} else {
a = z;
}
b = a + 1524;
c = (int) trunc((b - 122.1) / 365.25);
d = (int) trunc(365.25 * c);
e = (int) trunc((b - d) / 30.6001);
ymd_hmsm[DAY] = b - d - (int) trunc(30.6001 * e);
ymd_hmsm[MONTH] = (e < 14)
? (e - 1)
: (e - 13);
ymd_hmsm[YEAR] = (ymd_hmsm[MONTH] > 2)
? (c - 4716)
: (c - 4715);
for (int i = HOURS; i <= MILLIS; i++) {
switch (i) {
case HOURS:
f = f * 24.0;
break;
case MINUTES: case SECONDS:
f = f * 60.0;
break;
case MILLIS:
f = f * 1000.0;
break;
}
x = trunc(f);
ymd_hmsm[i] = (int) x;
f = f - x;
}
return ymd_hmsm;
}
Например, если функция вызывается с номером дня по юлианскому календарю 2457272,5, она вернет следующий вектор целых чисел, представляющий полночь 7 сентября 2015 года (день труда) в формате UTC:
[ 2015, 9, 7, 0, 0, 0, 0 ]
Редактировать: замечательная вещь в алгоритме Meeus заключается в том, что он правильно учитывает как високосные годы, так и столетние дни (включая исключение столетий). Он использует только целочисленную арифметику и арифметику с плавающей запятой и, скорее всего, будет более производительным, чем решения, требующие создания объектов из Java Calendar или Date-Time API.
person
scottb
schedule
18.12.2015