查询" ALL_DAY"使用CalendarContract.Instances结果事件错误的时区时区、错误、事件、结果

2023-09-07 22:28:12 作者:夙雪夜归寒

我使用CalendarContract.Instances得到一组日历活动。总的来说我的查询工作的罚款。然而,开始时间和结束时间为事件中的节假日日历回来在一个错误的时区。在我个人日历中的一个事件都配备正确的时间。

例如:

 元旦开始04:00 PM,2014年12月31日。 

在这里为

 歌剧开始02:00 PM,2015年1月11日。 
AllDup 重复文件查找工具官方免费下载 AllDup 重复文件查找工具 4.1.8.0

我使用的是完全相同的code同时显示:

 的SimpleDateFormat格式化=新的SimpleDateFormat(HH:MM A,D MMM YYYY,Locale.US);  logD(preFIX + I +:+ formatter.format(data.startTime)+;+ data.note); 

在哪里data.startTime映射到Instances.BEGIN和data.note映射到Instances.TITLE。歌剧院是显示在正确的时间,元旦显然是8小时关闭(我在美国太平洋时区)。

如果我在Android日历应用程序查看这些,都显示正确的时间。

很显然,我可以看看的日历事件来源于并相应地设置时区,使其显示正确的时间。不过,我希望有一个我是不知道的更妥善的解决。

下面是从光标获取事件价值code的喀嚓:

  @覆盖公共查看getView(INT位置,查看convertView,父母的ViewGroup){  ...  EventFields领域=新EventFields();  cursor.moveToPosition(位置);  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));  ...} 

下面的查询:

  @覆盖公共无效refreshData(字符串约束){  长开始= ...一些日期...  长端= ...另一个日期...  最后乌里URI = Uri.parse(CalendarContract.Instances.CONTENT_URI +/+                            Long.toString(开始)+/+                            Long.toString(结束));  //设置查询 - 投影顺序必须符合以上静。  最终的String [] =投影新的String [] {    Instances._ID,    Instances.EVENT_ID,    Instances.TITLE,    Instances.BEGIN,    Instances.END,    Instances.DURATION,    Instances.RRULE,    Instances.DESCRIPTION,  };  最后弦乐中将sortOrder = Instances.BEGIN;  串选择= NULL;  如果(约束!= NULL)    选择= Instances.TITLE +LIKE'%+ constraint.toString()+%';  光标= getActivity()。getContentResolver()查询(    URI,    投影,    选择,    空值,    排序);} 

对于上面的例子中,元旦

 元旦DTSTART = 14199.84亿和 

和它真正开始于下午4点的另一个事件有

 罗杰DTSTART = 1420052400000 

解决方案

由于在评论中讨论,我们确定这是关系到UTC时间显示全日事件的一个问题。

看起来这是just Android的如何处理它的。

在Android文档纵观格式时间类

  

公共布​​尔allDay结果  如果这是一个allDay事件。小时,分钟,第二场是全零,和日期显示在所有时区相同。

最后在 CalendarContract.Events文档

  

如果allDay被设置为1 eventTimezone必须TIMEZONE_UTC和时间必须对应于午夜边界

那么,你已经通过格式化全天事件做是正确的。

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

更新

在默认情况下,如果你不明确设置你的SimpleDateFormat的时区,将默认为您的设备的本地时区。

您BEGIN和END时间应回来UTC时间。

全天事件总是被设置为午夜在UTC时区,因此,格式化他们什么,但UTC时间会给你一个非午夜时间。

您可以使用继承域检查日历事件实例的时区:

  

EVENT_TIMEZONE

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

解决方案

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