Календарь, дающий неожиданные результаты на первый год

Я пытался выполнить это соревнование по код-гольфу в Java 7. Только для тех, кто не знает знать: code-golf должен выполнить определенную задачу как можно меньшим количеством байтов. Очевидно, что Java не является подходящим языком программирования для этого, особенно с такими языками, как Jelly; 05АВ1Е; пиф; и тому подобное, которые выполняют задачи в 1-15 байт, что будет 75-300 в Java, но я просто делаю это для удовольствия.

Вот мой текущий ответ по Java 7. Просто для справки, я также скопирую его сюда:

import java.util.*;String c(int y){String r="";Calendar c=Calendar.getInstance();c.set(1,y);c.set(2,0);for(int i=0;i++<11;c.add(2,1)){c.set(5,c.getActualMaximum(5));if(c.get(7)==2)r+=i+" ";}return r;}

import java.util.*;
class M{
  static String c(int year){
    String r = "";
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, 0);
    for(int i = 0; i++ < 11; calendar.add(Calendar.MONTH, 1)){
      calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
      if(calendar.get(Calendar.DAY_OF_WEEK) == 2){
        r += i+" ";
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c(1));
    System.out.println(c(297));
    System.out.println(c(1776));
    System.out.println(c(2000));
    System.out.println(c(2016));
    System.out.println(c(3385));
  }
}

Который выводит все 1-индексированные месяцы, последний день месяца которых является понедельником:

1 2 10 **
5 
9 
1 7 
2 10 
1 2 10

Как вы, возможно, заметили, когда вы сравниваете мои результаты с результатами связанного испытания, результаты за год 1 неверны.
Кто-нибудь знает, почему? Первоначально я думал, что Calendar.getInstance() имеет неправильный календарь по умолчанию, поэтому я изменил его на new GregorianCalendar(), как указано в задаче. Но я уже понял, что это календарь по умолчанию.

Почему за первый год получены неверные результаты?


person Kevin Cruijssen    schedule 27.10.2016    source источник


Ответы (1)


К сожалению, GregorianCalendar плохо назван. На самом деле это «юлианский / григорианский календарь с переключением между ними».

К счастью, вы можете использовать его как чистый григорианский календарь, установив это переключение в начале времени:

GregorianCalendar calendar = new GregorianCalendar();
calendar.setGregorianChange(new Date(Long.MIN_VALUE));

В этот момент с вашим текущим кодом вы получите ответ всего «4» — он не набирает 12 из-за ошибки «не на единицу» … вам нужно < 12, а не < 11.

person Jon Skeet    schedule 27.10.2016
comment
Ах, я действительно знал о том, что GregorianCalendar был и юлианским, и григорианским, но я не знал, что на самом деле это было причиной проблемы, и я не знал о setGregorianChange. Спасибо! Я изменил его на GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));, и он работает как шарм. P.S. Новая аватарка? :) - person Kevin Cruijssen; 27.10.2016