2015-01-26 2 views
4

Итак, это 26 января 2015 года, и у меня есть следующий код, запущенный на устройстве Android;Это ошибка в Android GregorianCalendar?

GregorianCalendar date = new GregorianCalendar(); 
SimpleDateFormat df = new SimpleDateFormat(); 

// Set date to 4 weeks ago, and then use it for the first BETWEEN date in the above query  
date.set(GregorianCalendar.WEEK_OF_YEAR, date.get(GregorianCalendar.WEEK_OF_YEAR)-4); 
System.out.println(df.format(new Date(date.getTimeInMillis()))); 
// Set date to 2 weeks time, and then use it for the second BETWEEN date in the above query 

date.set(GregorianCalendar.WEEK_OF_YEAR, date.get(GregorianCalendar.WEEK_OF_YEAR)+6); 
System.out.println(df.format(new Date(date.getTimeInMillis()))); 

И я получаю выход;

29/12/14 10:29 
09/02/14 10:29 

Запуск этого фрагмента на стандартной Java на машине Windows, показывает правильные результаты со второй датой как 09/02/15 10:29. Таким образом, на Android, он вернётся назад, когда мы просим, ​​чтобы дата вернулась на 4 недели, но когда мы просим его идти вперед на 6 недель (после нашей первоначальной даты), он не перевернет год вперед.

Я наблюдал это на 5.0.2 и 4.4.2

Так что вопрос, является ли это ошибка или каким-то свернутое предполагаемого поведения (особенности)?

ответ

2

Я довольно уверен, что это сложность, как определенные Calendar поля вычисляются и обрабатываются, и это не ошибка. Тот факт, что вы используете арифметические настройки, а не используя метод add(...), вероятно, также усложняет ситуацию.

Из документов ...

Первой недели месяца или года определяется как самый ранний семидневный период, начинающегося getFirstDayOfWeek() и содержащий, по меньшей мере, getMinimalDaysInFirstWeek() дней этого месяца или года ,

В этом случае первая неделя года, т.е. WEEK_OF_YEAR = 1, начинается с 4-го или 5-го января, в зависимости от того, если первый день недели установлен в воскресенье или в понедельник соответственно.

Класс Calendar класс абстрактный и различные реализации конкретных классов, которые его расширяют, могут вести себя по-другому, но допустимо иметь индекс 0 или даже -1 неделями в год. Тот факт, что даты 1 -> 3 или 1 -> 4 (в зависимости от первого дня недели), очевидно, относятся к 2015 году, означает, что неделя, начинающаяся 28 или 29 декабря, классифицируется как неделя 0.

26 Январь относится к WEEK_OF_YEAR = 4 (независимо от первого дня недели), и, следовательно, когда вы вычитаете 4 из текущего WEEK_OF_YEAR, он возвращает 0 и корректирует дату в понедельник на этой неделе, то есть 29 декабря.

Проблема возникает, когда вы добавляете 6 недель к ранее скорректированной дате - на данный момент это 29 декабря 2014 года. Как я уже сказал, вы используете арифметическую настройку, а не используя метод add(...).Поскольку вы не корректируете год вручную, он предполагает, что он должен оставаться в течение 2014 года и добавив 6 недель, которые вы вызываете переполнение/откат к началу 2014 года, вместо того, чтобы динамически регулировать YEAR, а также WEEK_OF_YEAR и т. Д.

+0

Принимается, потому что это объясняет нечетные результаты, которые я видел, и отвечает на прямой вопрос. Благодарю. –

+0

@ Rudi: Рад, что я мог пролить свет. Ключевым моментом является то, что любое поле, которое называется с помощью '_OF_' (примеры« HOUR_OF_DAY', 'WEEK_OF_YEAR',' DAY_OF_MONTH' и т. Д.), Обычно будет переполняться и откатываться к началу того, что они представляют. Это сложно, и, как я уже сказал, не ошибка, а странность. – Squonk

2

Для этого не следует использовать Calendar.set. Вы пытаетесь установить поле недели на недопустимое значение и надеетесь, что оно может определить ваше предполагаемое значение. Это может работать для JVM на рабочем столе, но вы не должны полагаться на него, и, судя по всему, реализация Android действительно обрабатывает его по-разному.

Вместо этого используется Calendar.add, что фактически делает то, что вы хотите: добавьте или вычтите из поля с соответствующими настройками.

date.add(GregorianCalendar.WEEK_OF_YEAR, -4); 
date.add(GregorianCalendar.WEEK_OF_YEAR, 6); 
+0

Спасибо. Это был не тот ответ, который я искал, но это был ответ, который мне нужен. –

Смежные вопросы