Query of “all_day” events using CalendarContract.Instances results in wrong time zone

五迷三道 提交于 2019-12-12 10:42:41

问题


I'm using CalendarContract.Instances to get a set of calendar events. In general my queries work fine. However, the begin and end times for events in the "holidays" calendar come back in a wrong time zone. Events in one of my personal calendars come with correct times.

For example:

New Year's day "begins" at 04:00 PM, 31 Dec 2014.

where as

Opera "begins" at 02:00 PM, 11 Jan 2015.

I'm using exactly the same code to display both:

  SimpleDateFormat formatter = new SimpleDateFormat ("hh:mm a, d MMM yyyy", Locale.US);
  logD (prefix + i + ": " + formatter.format (data.startTime) + "; " + data.note);

where data.startTime maps to Instances.BEGIN and data.note maps to Instances.TITLE. The Opera is showing at the correct time, New Year's day is obviously 8 hours off (I'm in the US Pacific time zone).

If I view these in the Android calendar app, both show with the correct time.

Obviously, I can look at which calendar the event comes from and set the time zone accordingly to make it show with the correct time. However, I'm hoping there's a more proper solution that I'm unaware of.

Here's a snip of code that gets the event values from the cursor:

@Override
public View getView (int position, View convertView, ViewGroup parent)
{
  ...
  EventFields fields = new EventFields();
  cursor.moveToPosition (position);
  fields.title = cursor.getString (cursor.getColumnIndex (Instances.TITLE));
  fields.dtStart = cursor.getLong (cursor.getColumnIndex (Instances.BEGIN));
  fields.dtEnd = cursor.getLong (cursor.getColumnIndex (Instances.END));
  fields.iCalDuration = cursor.getString (cursor.getColumnIndex (Instances.DURATION));
  fields.rrule = cursor.getString (cursor.getColumnIndex (Instances.RRULE));
  ...
}

Here's the query:

@Override
public void refreshData (String constraint)
{
  long begin = ... some date ...
  long end = ... another date ...

  final Uri uri = Uri.parse(CalendarContract.Instances.CONTENT_URI + "/" + 
                            Long.toString(begin) + "/" + 
                            Long.toString(end));

  // Setup query  - projection ordering must match statics above.
  final String[] projection = new String[] {
    Instances._ID,
    Instances.EVENT_ID,
    Instances.TITLE,
    Instances.BEGIN,
    Instances.END,
    Instances.DURATION,
    Instances.RRULE,
    Instances.DESCRIPTION,
  };
  final String sortOrder = Instances.BEGIN;

  String selection = null;
  if (constraint != null)
    selection = Instances.TITLE + " like '%" + constraint.toString() + "%'"; 

  cursor = getActivity().getContentResolver().query (
    uri,
    projection, 
    selection,
    null,
    sortOrder);
}

For the example above, New Year's Day

New Year's day dtStart = 1419984000000 and

And another event which really starts at 4pm has

Roger          dtStart = 1420052400000

回答1:


As discussed in the comments, we determined that this is a problem related to All Day events displaying times in UTC.

It looks like this is just how Android handles it.

Looking at the Format Time class in the Android Docs

public boolean allDay
True if this is an allDay event. The hour, minute, second fields are all zero, and the date is displayed the same in all time zones.

And finally on the CalendarContract.Events docs

If allDay is set to 1 eventTimezone must be TIMEZONE_UTC and the time must correspond to a midnight boundary.

So what you have done by formatting all day events is correct

simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

Update

By default, if you don't explicitly set the timezone of your SimpleDateFormat, it will default to your device's local timezone.

Your BEGIN and END times should come back in UTC time.

All Day Events are always set to midnight in the UTC timezone, so formatting them in anything but the UTC time zone will give you a non-midnight time.

You can check the Calendar Event Instance's timezone using the inherited field:

EVENT_TIMEZONE




回答2:


Try adding: formatter.setTimeZone(TimeZone.getTimeZone("US/Pacific"));




回答3:


You can actually set time zones on your calendars. Double check that the time zones of the two calendars you compare are set to the same value.



来源:https://stackoverflow.com/questions/27516398/query-of-all-day-events-using-calendarcontract-instances-results-in-wrong-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!