Java
Chúng ta đều biết API Ngày / Giờ Java không sử dụng được và bị hỏng. Vì vậy, đây là một bản sửa lỗi không (ít nhất là trực tiếp) sử dụng bất kỳ API hiện có nào. Nó thậm chí còn hỗ trợ giây nhuận! :) Đầu ra là trong UTC.
import java.lang.reflect.Field;
import java.net.HttpCookie;
import java.util.*;
public class FixedTimeAPI4Java {
private static final List<Integer> MONTHS_WITH_30_DAYS = Arrays.asList(4, 6, 9, 11);
private static final List<Integer> YEARS_WITH_LEAP_SECOND_IN_DECEMBER = Arrays.asList(1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1987, 1989, 1990, 1995, 1998, 2005, 2008);
private static final List<Integer> YEARS_WITH_LEAP_SECOND_IN_JUNE = Arrays.asList(1972, 1981, 1982, 1983, 1985, 1992, 1993, 1994, 1997, 2012);
/**
* Returns the UTC time, at the time of method invocation, with millisecond
* precision, in format <code>yyyy-MM-dd HH:mm:ss.SSS</code>.
*/
public String getTime() throws Exception {
// The cookie is only used for accessing current system time
HttpCookie cookie = new HttpCookie("Offline", "Cookie");
Field created = HttpCookie.class.getDeclaredField("whenCreated");
created.setAccessible(true);
long millisecondsSinceEpoch = created.getLong(cookie);
long fullSecondsSinceEpoch = millisecondsSinceEpoch / 1000L;
int year = 1970, month = 1, dayOfMonth = 1, hour = 0, minute = 0, second = 0,
millisecond = (int)(millisecondsSinceEpoch - (fullSecondsSinceEpoch * 1000L));
ticks:
for (;; year++) {
for (month = 1; month <= 12; month++) {
for (dayOfMonth = 1; dayOfMonth <= daysInMonth(month, year); dayOfMonth++) {
for (hour = 0; hour < 24; hour++) {
for (minute = 0; minute < 60; minute++) {
for (second = 0; second < secondsInMinute(minute, hour, dayOfMonth, month, year); second++, fullSecondsSinceEpoch--) {
if (fullSecondsSinceEpoch == 0) {
break ticks;
}
}
}
}
}
}
}
return String.format("%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month,
dayOfMonth, hour, minute, second, millisecond);
}
/**
* Returns the seconds in the given minute of the given hour/day/month/year,
* taking into account leap seconds that can be added to the last minute of
* June or December.
*/
private static int secondsInMinute(int minute, int hour, int day, int month, int year) {
return (minute == 59 && hour == 23 && ((day == 30 && month == 6) || (day == 31 && month == 12)))
? 60 + leapSecondsInMonth( month, year)
: 60;
}
/**
* Returns the number of days in the given month of the given year.
*/
private static int daysInMonth(int month, int year) {
return month == 2 ? isLeapYear(year) ? 29 : 28
: MONTHS_WITH_30_DAYS.contains(month) ? 30
: 31;
}
/**
* Returns whether the given year is a leap year or not.
* A leap year is every 4th year, but not if the year is divisible by 100, unless if it's divisible by 400.
*/
private static boolean isLeapYear(int year) {
return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? true : false;
}
/**
* Returns the number of leap seconds that were added to UTC time at the end of the given month and year.
* Leap seconds are added (by the decison of International Earth Rotation Service / Paris Observatory)
* in order to keep UTC within 0.9 seconds of international atomic time (TAI).
* <p>TODO: implement parser for updated list at http://www.ietf.org/timezones/data/leap-seconds.list :)
*/
private static int leapSecondsInMonth(int month, int year) {
return (year < 1972 || year > 2012) ? 0
: (month == 6 && YEARS_WITH_LEAP_SECOND_IN_JUNE.contains(year)) ? 1
: (month == 12 && YEARS_WITH_LEAP_SECOND_IN_DECEMBER.contains(year)) ? 1
: 0;
}
public final static void main(String[] args) throws Exception {
System.out.println(new FixedTimeAPI4Java().getTime());
}
}