Программа с последующим выводом. Кто-нибудь, пожалуйста, объясните мне, почему 10 000 000 миллисекунд с 1 января 1970 года равняются 31 ноября 1969 года. Кто-нибудь, пожалуйста, объясните, что не так с моим предположением о том, что первый тест должен дать время в 10 000 000 миллисекунд с 1 января 1970 года. Числа меньше 10 000 000 дают тот же результат.
public static void main(String[] args) {
String x = "10000000";
long l = new Long(x).longValue();
System.out.println("Long value: " + l);
Calendar c = new GregorianCalendar();
c.setTimeInMillis(l);
System.out.println("Calendar time in Millis: " + c.getTimeInMillis());
String origDate = c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH);
System.out.println("Date in YYYY-MM-DD format: " + origDate);
x = "1000000000000";
l = new Long(x).longValue();
System.out.println("\nLong value: " + l);
c.setTimeInMillis(l);
System.out.println("Calendar time in Millis: " + c.getTimeInMillis());
origDate = c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH);
System.out.println("Date in YYYY-MM-DD format: " + origDate);
}
Long value: 10000000
Calendar time in Millis: 10000000
Date in YYYY-MM-DD format: 1969-11-31
Long value: 1000000000000
Calendar time in Millis: 1000000000000
Date in YYYY-MM-DD format: 2001-8-8




Вы можете разобраться сами, если поменяете свой первый c.setTimeInMillis(l); на c.clear();
Даты, которые вы печатаете из Calendar, являются локальными для вашего часового пояса, тогда как эпоха определяется как полночь 01.01.1970 по всемирному координированному времени. Итак, если вы живете в часовом поясе к западу от UTC, тогда ваша дата будет отображаться как 1969-12-31, хотя (в UTC) это все еще 1970-01-01.
Во-первых, c.get(Calendar.MONTH) возвращает 0 для января, 1 для февраля и т. д.
Во-вторых, используйте DateFormat для вывода дат.
В-третьих, ваши проблемы - отличный пример того, насколько неудобен Java Date API. По возможности используйте Joda Time API. Это сделает вашу жизнь несколько проще.
Вот лучший пример вашего кода, который указывает часовой пояс:
public static void main(String[] args) {
final DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
long l = 10000000L;
System.out.println("Long value: " + l);
Calendar c = new GregorianCalendar();
c.setTimeInMillis(l);
System.out.println("Date: " + dateFormat.format(c.getTime()));
l = 1000000000000L;
System.out.println("\nLong value: " + l);
c.setTimeInMillis(l);
System.out.println("Date: " + dateFormat.format(c.getTime()));
}
Календарь # setTimeInMillis () устанавливает время календаря равным количеству миллисекунд после 1 января 1970 г. время по Гринвичу.
Календарь # get () возвращает запрошенное поле с поправкой на часовой пояс календаря, который по умолчанию равен часовой пояс вашего компьютера.
Это должно работать так, как вы ожидаете, если вы укажете часовой пояс «GMT» при создании календаря:
Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Ваш часовой пояс, скорее всего, отстает от GMT (например, GMT-5), поэтому 10 000 000 мс от эпохи - это 31 декабря 1969 года в вашем часовом поясе, но поскольку в java.util.Calendar месяцы отсчитываются от нуля, преобразование Calendar в текст некорректно, и вы получаете 1969-11-31 вместо ожидаемого 1969-12-31.
К сожалению, java.util.Date и java.util.Calendar были плохо спроектированы, что привело к такого рода путанице.
Очень полезно; Вы ответили на мой вопрос немного косвенно. Больше всего меня смутил часовой пояс. Мы очень ценим улучшенный код.