android - 使用 CalendarContract.Instances 查询 "all_day"事件导致时区错误

标签 android calendarcontract

我正在使用 CalendarContract.Instances 获取一组日历事件。一般来说,我的查询工作正常。但是,“假期”日历中事件的开始和结束时间在错误的时区返回。我的一个个人日历中的事件都有正确的时间。

例如:

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

在哪里

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

我使用完全相同的代码来显示两者:

  SimpleDateFormat formatter = new 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 日历应用程序中查看这些,两者都会显示正确的时间。

显然,我可以查看事件来自哪个日历并相应地设置时区以使其以正确的时间显示。但是,我希望有一个我不知道的更合适的解决方案。

这是从光标获取事件值的代码 fragment :

@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));
  ...
}

这是查询:

@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);
}

如上例,元旦

New Year's day dtStart = 1419984000000 and

另一个真正在下午 4 点开始的 Activity 是

Roger          dtStart = 1420052400000

最佳答案

正如评论中所讨论的,我们确定这是与 All Day 事件以 UTC 显示时间相关的问题。

看起来这是just how Android handles it .

查看 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.

最后是 CalendarContract.Events docs

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

所以你所做的格式化全天事件是正确的

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

更新

默认情况下,如果您没有明确设置 SimpleDateFormat 的时区,它将默认为您设备的本地时区。

您的 BEGIN 和 END 时间应该以 UTC 时间返回。

全天事件始终设置为 UTC 时区的午夜,因此将它们格式化为 UTC 时区以外的任何时间都会为您提供非午夜时间。

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

EVENT_TIMEZONE

关于android - 使用 CalendarContract.Instances 查询 "all_day"事件导致时区错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27516398/

相关文章:

android - 在 android 中创建一个匹配所有 Intent 的 IntentFilter

android - android View 模型之间的相互通信

android - 使用 Google Daydream sdk 为 Lenovo mirage solo 耳机开发应用程序

java - 如何在Android Studio中使用Ant工具构建项目?

java - 发送文件到android服务器

android - Android 5.0 中缺少 CalendarContract.Events._ID

Android 日历事件不显示