Календарь событий Android на весь день отключен на один день для GMT +x областей

Я написал простой код для вставки события на весь день в календарь, используя руководство с официального сайта. http://developer.android.com/guide/topics/providers/calendar-provider.html

    ContentResolver cr = context.getContentResolver();
    ContentValues values = new ContentValues();
    values.put(Events.DTSTART, dueDate.getTime());
    values.put(Events.ALL_DAY, true);   
    values.put(Events.DTEND, dueDate.getTime());
    values.put(Events.TITLE, "Some Event");
    values.put(Events.CALENDAR_ID, mCalID);
    TimeZone tz = TimeZone.getDefault();
    values.put(Events.EVENT_TIMEZONE, tz.getID());
   Uri uri = cr.insert(Events.CONTENT_URI, values);

Я обнаружил, что при открытии приложения Google Calendar на устройстве Acer под управлением 4.03 введенная дата была перенесена на 1 день назад. Мой местный часовой пояс - Сидней, который GMT+10.

Поэтому я пошел в настройки, изменил местный часовой пояс на американский восточный (GMT -5) и запустил тот же код, и даты не изменились. Затем я изменил часовой пояс на GMT+2 в Стамбуле, и даты изменились. Затем я перешел на лондонское время по Гринвичу 0, и сдвига не было.

Когда я делал не все дневные события, правильное время было введено в календарь независимо от часового пояса.

Самым близким сообщением об ошибке, которое я нашел, было это http://code.google.com/p/android/issues/detail?id=14051

Я что-то упустил в коде, или другие тоже сталкивались с этим.

Изменить при дальнейшей проверке при чтении данных о событиях с помощью распознавателя содержимого

  ContentResolver cr = context.getContentResolver();
Uri uri =  CalendarContract.Events.CONTENT_URI; 
String selection =CalendarContract.Events._ID + "=?";
String [] selectionArgs = new String[]{String.valueOf(eventID)}; 

Значение long при конвертации в дату было правильной датой и временем, например. 14 февраля 2013 12.00 AEST (Сиднейское время). Таким образом, проблема должна заключаться в том, как Google Calendar читает эти значения. Когда я вручную добавил событие на весь день из приложения "Календарь" в Android, и считал время с помощью распознавателя контента, это была дата и 11:00 по AEST (время Сиднея), что соответствует +11 по Гринвичу в Сиднее. Таким образом, события дня должны быть введены в GMT, чтобы избежать этого, но в документации нет упоминания об этом.

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

3 ответа

Пара идей:

  1. "независимость" часового пояса от событий на весь день (как если бы у них было время по Гринвичу)
  2. международная линия дат

[1] "Если для allDay установлено значение 1, eventTimezone должен иметь значение TIMEZONE_UTC, а время должно соответствовать границе полуночи".

[2] http://developer.android.com/reference/android/provider/CalendarContract.Events.html

В документации для CalendarContract.EventsColumns указано "Если для allDay установлено значение 1, eventTimezone должен иметь значение TIMEZONE_UTC, а время должно соответствовать границе полуночи".

Мое решение, чтобы гарантировать, что ожидаемые даты будут возвращены после запроса API, состояло в следующем: a) Установите значения начала и конца события с датами, выровненными по UTC. б) Отрегулируйте время, возвращаемое после запроса, чтобы учесть часовой пояс устройства и летнее время.

а)

@Before
public void setup(){
    ...
    mJavaCalendar = Calendar.getInstance();
    mInputStart = getUtcDate(
            mJavaCalendar.get(Calendar.YEAR),
            mJavaCalendar.get(Calendar.MONTH),
            mJavaCalendar.get(Calendar.DAY_OF_MONTH));
}

private long getUtcDate(int year, int month, int day){
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    calendar.set(year, month, day,0, 0, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar.getTimeInMillis();
}

@Test
public void jCalAlldayTzDflt0000To2400(){
    mTodayEvent.setEventStart(mInputStart);
    mTodayEvent.setEventEnd(mTodayEvent.getEventStart() +  DateUtils.DAY_IN_MILLIS);
    mTodayEvent.setAllDay(true);
    ...
}

б)

public static long getTzAdjustedDate(long date){
    TimeZone tzDefault = TimeZone.getDefault();
    return date - (tzDefault.getRawOffset() + tzDefault.getDSTSavings());
}

public void getCorrectDate(cursor){
    isAllDay() == 1 ? DateTimeUtils.getTzAdjustedDate(cursor.getLong(INST_PROJECTION_BEGIN_INDEX)) :
            cursor.getLong(INST_PROJECTION_BEGIN_INDEX));

Надеюсь, это поможет.

Если мое мероприятие проводилось в течение всего дня, я конвертировал его в местное время. Это сделало мероприятие на весь день верным. Если это не весь день, я оставил это как обычно. Я не думаю, что это отличное решение, но оно работает, и если кто-то видит проблему с этим, то дайте мне знать.

        var startDate = yourCalendarEvent.StartDate;
        if (yourCalendarEvent.IsAllDay)
        {
            startDate = startDate.ToLocalTime();
        }
        Java.Util.GregorianCalendar calStartDate = new Java.Util.GregorianCalendar(startDate.Year, startDate.Month - 1, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second);
        intent.PutExtra(CalendarContract.ExtraEventBeginTime, calStartDate.TimeInMillis);
Другие вопросы по тегам