diff --git a/android/src/com/google/zxing/client/android/history/HistoryManager.java b/android/src/com/google/zxing/client/android/history/HistoryManager.java index 594bfb955..aa636d298 100644 --- a/android/src/com/google/zxing/client/android/history/HistoryManager.java +++ b/android/src/com/google/zxing/client/android/history/HistoryManager.java @@ -67,7 +67,8 @@ public final class HistoryManager { private static final String[] ID_COL_PROJECTION = { DBHelper.ID_COL }; private static final String[] ID_DETAIL_COL_PROJECTION = { DBHelper.ID_COL, DBHelper.DETAILS_COL }; - private static final DateFormat EXPORT_DATE_TIME_FORMAT = DateFormat.getDateTimeInstance(); + private static final DateFormat EXPORT_DATE_TIME_FORMAT = + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); private final Activity activity; diff --git a/android/src/com/google/zxing/client/android/result/AddressBookResultHandler.java b/android/src/com/google/zxing/client/android/result/AddressBookResultHandler.java index f5999675b..b61035ef0 100644 --- a/android/src/com/google/zxing/client/android/result/AddressBookResultHandler.java +++ b/android/src/com/google/zxing/client/android/result/AddressBookResultHandler.java @@ -27,7 +27,7 @@ import android.text.SpannableString; import android.text.style.StyleSpan; import java.text.DateFormat; -import java.text.ParsePosition; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -45,6 +45,12 @@ public final class AddressBookResultHandler extends ResultHandler { new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH), new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH), }; + static { + for (DateFormat format : DATE_FORMATS) { + format.setLenient(false); + } + } + private static final int[] BUTTON_TEXTS = { R.string.button_add_contact, R.string.button_show_map, @@ -148,13 +154,11 @@ public final class AddressBookResultHandler extends ResultHandler { } private static Date parseDate(String s) { - for (DateFormat currentFomat : DATE_FORMATS) { - synchronized (currentFomat) { - currentFomat.setLenient(false); - Date result = currentFomat.parse(s, new ParsePosition(0)); - if (result != null) { - return result; - } + for (DateFormat currentFormat : DATE_FORMATS) { + try { + return currentFormat.parse(s); + } catch (ParseException e) { + // continue } } return null; @@ -191,7 +195,7 @@ public final class AddressBookResultHandler extends ResultHandler { if (birthday != null && birthday.length() > 0) { Date date = parseDate(birthday); if (date != null) { - ParsedResult.maybeAppend(DateFormat.getDateInstance().format(date.getTime()), contents); + ParsedResult.maybeAppend(DateFormat.getDateInstance(DateFormat.MEDIUM).format(date.getTime()), contents); } } ParsedResult.maybeAppend(result.getNote(), contents); diff --git a/android/src/com/google/zxing/client/android/result/CalendarResultHandler.java b/android/src/com/google/zxing/client/android/result/CalendarResultHandler.java index 497e130ac..ae921af62 100644 --- a/android/src/com/google/zxing/client/android/result/CalendarResultHandler.java +++ b/android/src/com/google/zxing/client/android/result/CalendarResultHandler.java @@ -23,23 +23,16 @@ import com.google.zxing.client.result.ParsedResult; import android.app.Activity; import java.text.DateFormat; -import java.text.ParsePosition; -import java.text.SimpleDateFormat; -import java.util.Calendar; import java.util.Date; -import java.util.GregorianCalendar; -import java.util.Locale; /** * Handles calendar entries encoded in QR Codes. * * @author dswitkin@google.com (Daniel Switkin) + * @author Sean Owen */ public final class CalendarResultHandler extends ResultHandler { - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); - private static final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ENGLISH); - private static final int[] buttons = { R.string.button_add_calendar }; @@ -64,6 +57,7 @@ public final class CalendarResultHandler extends ResultHandler { if (index == 0) { addCalendarEvent(calendarResult.getSummary(), calendarResult.getStart(), + calendarResult.isStartAllDay(), calendarResult.getEnd(), calendarResult.getLocation(), calendarResult.getDescription()); @@ -72,16 +66,25 @@ public final class CalendarResultHandler extends ResultHandler { @Override public CharSequence getDisplayContents() { + CalendarParsedResult calResult = (CalendarParsedResult) getResult(); StringBuilder result = new StringBuilder(100); - ParsedResult.maybeAppend(calResult.getSummary(), result); - String startString = calResult.getStart(); - appendTime(startString, result, false, false); - String endString = calResult.getEnd(); - if (endString != null) { - boolean sameStartEnd = startString.equals(endString); - appendTime(endString, result, true, sameStartEnd); + ParsedResult.maybeAppend(calResult.getSummary(), result); + + Date start = calResult.getStart(); + ParsedResult.maybeAppend(format(calResult.isStartAllDay(), start), result); + + Date end = calResult.getEnd(); + if (end != null) { + if (calResult.isEndAllDay() && !start.equals(end)) { + // Show only year/month/day + // if it's all-day and this is the end date, it's exclusive, so show the user + // that it ends on the day before to make more intuitive sense. + // But don't do it if the event already (incorrectly?) specifies the same start/end + end = new Date(end.getTime() - 24 * 60 * 60 * 1000); + } + ParsedResult.maybeAppend(format(calResult.isEndAllDay(), end), result); } ParsedResult.maybeAppend(calResult.getLocation(), result); @@ -90,38 +93,14 @@ public final class CalendarResultHandler extends ResultHandler { return result.toString(); } - private static void appendTime(String when, StringBuilder result, boolean end, boolean sameStartEnd) { - if (when.length() == 8) { - // Show only year/month/day - Date date; - synchronized (DATE_FORMAT) { - date = DATE_FORMAT.parse(when, new ParsePosition(0)); - } - // if it's all-day and this is the end date, it's exclusive, so show the user - // that it ends on the day before to make more intuitive sense. - // But don't do it if the event already (incorrectly?) specifies the same start/end - if (end && !sameStartEnd) { - date = new Date(date.getTime() - 24 * 60 * 60 * 1000); - } - ParsedResult.maybeAppend(DateFormat.getDateInstance().format(date.getTime()), result); - } else { - // The when string can be local time, or UTC if it ends with a Z - Date date; - synchronized (DATE_TIME_FORMAT) { - date = DATE_TIME_FORMAT.parse(when.substring(0, 15), new ParsePosition(0)); - } - long milliseconds = date.getTime(); - if (when.length() == 16 && when.charAt(15) == 'Z') { - Calendar calendar = new GregorianCalendar(); - // Account for time zone difference - milliseconds += calendar.get(Calendar.ZONE_OFFSET); - // Might need to correct for daylight savings time, but use target time since - // now might be in DST but not then, or vice versa - calendar.setTime(new Date(milliseconds)); - milliseconds += calendar.get(Calendar.DST_OFFSET); - } - ParsedResult.maybeAppend(DateFormat.getDateTimeInstance().format(milliseconds), result); + private static String format(boolean allDay, Date date) { + if (date == null) { + return null; } + DateFormat format = allDay + ? DateFormat.getDateInstance(DateFormat.MEDIUM) + : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); + return format.format(date); } @Override diff --git a/android/src/com/google/zxing/client/android/result/ResultHandler.java b/android/src/com/google/zxing/client/android/result/ResultHandler.java index bec4209b1..3f9e123e1 100644 --- a/android/src/com/google/zxing/client/android/result/ResultHandler.java +++ b/android/src/com/google/zxing/client/android/result/ResultHandler.java @@ -41,15 +41,9 @@ import android.provider.ContactsContract; import android.util.Log; import android.view.View; -import java.text.DateFormat; -import java.text.ParsePosition; -import java.text.SimpleDateFormat; -import java.util.Calendar; import java.util.Collection; import java.util.Date; -import java.util.GregorianCalendar; import java.util.Locale; -import java.util.TimeZone; /** * A base class for the Android-specific barcode handlers. These allow the app to polymorphically @@ -60,21 +54,12 @@ import java.util.TimeZone; * instance is needed to launch an intent. * * @author dswitkin@google.com (Daniel Switkin) + * @author Sean Owen */ public abstract class ResultHandler { private static final String TAG = ResultHandler.class.getSimpleName(); - private static final DateFormat DATE_FORMAT; - static { - DATE_FORMAT = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); - // For dates without a time, for purposes of interacting with Android, the resulting timestamp - // needs to be midnight of that day in GMT. See: - // http://code.google.com/p/android/issues/detail?id=8330 - DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); - } - private static final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ENGLISH); - private static final String GOOGLE_SHOPPER_PACKAGE = "com.google.android.apps.shopper"; private static final String GOOGLE_SHOPPER_ACTIVITY = GOOGLE_SHOPPER_PACKAGE + ".results.SearchResultsActivity"; @@ -223,21 +208,22 @@ public abstract class ResultHandler { * versions of the system have a bug where the event title will not be filled out. * * @param summary A description of the event - * @param start The start time as yyyyMMdd or yyyyMMdd'T'HHmmss or yyyyMMdd'T'HHmmss'Z' - * @param end The end time as yyyyMMdd or yyyyMMdd'T'HHmmss or yyyyMMdd'T'HHmmss'Z' + * @param start The start time + * @param allDay if true, event is considered to be all day starting from start time + * @param end The end time (optional) * @param location a text description of the event location * @param description a text description of the event itself */ final void addCalendarEvent(String summary, - String start, - String end, + Date start, + boolean allDay, + Date end, String location, String description) { Intent intent = new Intent(Intent.ACTION_EDIT); intent.setType("vnd.android.cursor.item/event"); - long startMilliseconds = calculateMilliseconds(start); + long startMilliseconds = start.getTime(); intent.putExtra("beginTime", startMilliseconds); - boolean allDay = start.length() == 8; if (allDay) { intent.putExtra("allDay", true); } @@ -250,7 +236,7 @@ public abstract class ResultHandler { endMilliseconds = startMilliseconds; } } else { - endMilliseconds = calculateMilliseconds(end); + endMilliseconds = end.getTime(); } intent.putExtra("endTime", endMilliseconds); intent.putExtra("title", summary); @@ -259,31 +245,6 @@ public abstract class ResultHandler { launchIntent(intent); } - private static long calculateMilliseconds(String when) { - if (when.length() == 8) { - // Only contains year/month/day - Date date; - synchronized (DATE_FORMAT) { - date = DATE_FORMAT.parse(when, new ParsePosition(0)); - } - // Note this will be relative to GMT, not the local time zone - return date.getTime(); - } else { - // The when string can be local time, or UTC if it ends with a Z - Date date; - synchronized (DATE_TIME_FORMAT) { - date = DATE_TIME_FORMAT.parse(when.substring(0, 15), new ParsePosition(0)); - } - long milliseconds = date.getTime(); - if (when.length() == 16 && when.charAt(15) == 'Z') { - Calendar calendar = new GregorianCalendar(); - int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); - milliseconds += offset; - } - return milliseconds; - } - } - final void addPhoneOnlyContact(String[] phoneNumbers,String[] phoneTypes) { addContact(null, null, phoneNumbers, phoneTypes, null, null, null, null, null, null, null, null, null, null); } @@ -495,7 +456,12 @@ public abstract class ResultHandler { } final void openURL(String url) { - launchIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + try { + launchIntent(intent); + } catch (ActivityNotFoundException anfe) { + Log.w(TAG, "Nothing available to handle " + intent); + } } final void webSearch(String query) { diff --git a/core/src/com/google/zxing/client/result/CalendarParsedResult.java b/core/src/com/google/zxing/client/result/CalendarParsedResult.java index f364e6790..e3ee0b698 100644 --- a/core/src/com/google/zxing/client/result/CalendarParsedResult.java +++ b/core/src/com/google/zxing/client/result/CalendarParsedResult.java @@ -16,14 +16,37 @@ package com.google.zxing.client.result; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; +import java.util.regex.Pattern; + /** * @author Sean Owen */ public final class CalendarParsedResult extends ParsedResult { + private static final Pattern DATE_TIME = Pattern.compile("[0-9]{8}(T[0-9]{6}Z?)?"); + + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); + static { + // For dates without a time, for purposes of interacting with Android, the resulting timestamp + // needs to be midnight of that day in GMT. See: + // http://code.google.com/p/android/issues/detail?id=8330 + DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); + } + private static final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ENGLISH); + private final String summary; - private final String start; - private final String end; + private final Date start; + private final boolean startAllDay; + private final Date end; + private final boolean endAllDay; private final String location; private final String attendee; private final String description; @@ -31,32 +54,23 @@ public final class CalendarParsedResult extends ParsedResult { private final double longitude; public CalendarParsedResult(String summary, - String start, - String end, - String location, - String attendee, - String description) { - this(summary, start, end, location, attendee, description, Double.NaN, Double.NaN); - } - - public CalendarParsedResult(String summary, - String start, - String end, + String startString, + String endString, String location, String attendee, String description, double latitude, double longitude) { super(ParsedResultType.CALENDAR); - validateDate(start); this.summary = summary; - this.start = start; - if (end != null) { - validateDate(end); - this.end = end; - } else { - this.end = null; + try { + this.start = parseDate(startString); + this.end = endString == null ? null : parseDate(endString); + } catch (ParseException pe) { + throw new IllegalArgumentException(pe.toString()); } + this.startAllDay = startString.length() == 8; + this.endAllDay = endString != null && endString.length() == 8; this.location = location; this.attendee = attendee; this.description = description; @@ -69,23 +83,34 @@ public final class CalendarParsedResult extends ParsedResult { } /** - *

We would return the start and end date as a {@link java.util.Date} except that this code - * needs to work under JavaME / MIDP and there is no date parsing library available there, such - * as {@code java.text.SimpleDateFormat}.

See validateDate() for the return format. - * - * @return start time formatted as a RFC 2445 DATE or DATE-TIME.

+ * @return start time */ - public String getStart() { + public Date getStart() { return start; } /** - * @see #getStart(). May return null if the event has no duration. + * @return true if start time was specified as a whole day */ - public String getEnd() { + public boolean isStartAllDay() { + return startAllDay; + } + + /** + * May return null if the event has no duration. + * @see #getStart() + */ + public Date getEnd() { return end; } + /** + * @return true if end time was specified as a whole day + */ + public boolean isEndAllDay() { + return endAllDay; + } + public String getLocation() { return location; } @@ -110,8 +135,8 @@ public final class CalendarParsedResult extends ParsedResult { public String getDisplayResult() { StringBuilder result = new StringBuilder(100); maybeAppend(summary, result); - maybeAppend(start, result); - maybeAppend(end, result); + maybeAppend(format(startAllDay, start), result); + maybeAppend(format(endAllDay, end), result); maybeAppend(location, result); maybeAppend(attendee, result); maybeAppend(description, result); @@ -119,36 +144,48 @@ public final class CalendarParsedResult extends ParsedResult { } /** - * RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021) or DATE-TIME - * (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC). + * Parses a string as a date. RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021) + * or DATE-TIME (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC). * - * @param date The string to validate + * @param when The string to parse + * @throws ParseException if not able to parse as a date */ - private static void validateDate(CharSequence date) { - if (date != null) { - int length = date.length(); - if (length != 8 && length != 15 && length != 16) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < 8; i++) { - if (!Character.isDigit(date.charAt(i))) { - throw new IllegalArgumentException(); - } - } - if (length > 8) { - if (date.charAt(8) != 'T') { - throw new IllegalArgumentException(); - } - for (int i = 9; i < 15; i++) { - if (!Character.isDigit(date.charAt(i))) { - throw new IllegalArgumentException(); - } - } - if (length == 16 && date.charAt(15) != 'Z') { - throw new IllegalArgumentException(); - } + private static Date parseDate(String when) throws ParseException { + if (!DATE_TIME.matcher(when).matches()) { + throw new ParseException(when, 0); + } + if (when.length() == 8) { + // Show only year/month/day + return DATE_FORMAT.parse(when); + } else { + // The when string can be local time, or UTC if it ends with a Z + Date date; + if (when.length() == 16 && when.charAt(15) == 'Z') { + date = DATE_TIME_FORMAT.parse(when.substring(0, 15)); + Calendar calendar = new GregorianCalendar(); + long milliseconds = date.getTime(); + // Account for time zone difference + milliseconds += calendar.get(Calendar.ZONE_OFFSET); + // Might need to correct for daylight savings time, but use target time since + // now might be in DST but not then, or vice versa + calendar.setTime(new Date(milliseconds)); + milliseconds += calendar.get(Calendar.DST_OFFSET); + date = new Date(milliseconds); + } else { + date = DATE_TIME_FORMAT.parse(when); } + return date; } } + private static String format(boolean allDay, Date date) { + if (date == null) { + return null; + } + DateFormat format = allDay + ? DateFormat.getDateInstance(DateFormat.MEDIUM) + : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); + return format.format(date); + } + } diff --git a/core/test/src/com/google/zxing/client/result/CalendarParsedResultTestCase.java b/core/test/src/com/google/zxing/client/result/CalendarParsedResultTestCase.java index 03358ccbc..239632a4e 100644 --- a/core/test/src/com/google/zxing/client/result/CalendarParsedResultTestCase.java +++ b/core/test/src/com/google/zxing/client/result/CalendarParsedResultTestCase.java @@ -19,8 +19,14 @@ package com.google.zxing.client.result; import com.google.zxing.BarcodeFormat; import com.google.zxing.Result; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.TimeZone; + /** * Tests {@link CalendarParsedResult}. * @@ -30,6 +36,17 @@ public final class CalendarParsedResultTestCase extends Assert { private static final double EPSILON = 0.0000000001; + private static final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH); + static { + DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); + } + + @Before + public void setUp() { + Locale.setDefault(Locale.ENGLISH); + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + } + @Test public void testStartEnd() { doTest( @@ -125,8 +142,8 @@ public final class CalendarParsedResultTestCase extends Assert { "Meeting with a friend\nlook at homepage first\n\n\n \n", "Summary line", "Location, with, escaped, commas", - "20111110T110000", - "20111110T120000"); + "20111110T110000Z", + "20111110T120000Z"); } @Test @@ -135,24 +152,24 @@ public final class CalendarParsedResultTestCase extends Assert { "DTSTART;VALUE=DATE:20111110\n" + "DTEND;VALUE=DATE:20111110\n" + "END:VEVENT", - null, null, null, "20111110", "20111110"); + null, null, null, "20111110T000000Z", "20111110T000000Z"); } private static void doTest(String contents, String description, String summary, String location, - String start, - String end) { - doTest(contents, description, summary, location, start, end, null, Double.NaN, Double.NaN); + String startString, + String endString) { + doTest(contents, description, summary, location, startString, endString, null, Double.NaN, Double.NaN); } private static void doTest(String contents, String description, String summary, String location, - String start, - String end, + String startString, + String endString, String attendee, double latitude, double longitude) { @@ -163,8 +180,8 @@ public final class CalendarParsedResultTestCase extends Assert { assertEquals(description, calResult.getDescription()); assertEquals(summary, calResult.getSummary()); assertEquals(location, calResult.getLocation()); - assertEquals(start, calResult.getStart()); - assertEquals(end, calResult.getEnd()); + assertEquals(startString, DATE_TIME_FORMAT.format(calResult.getStart())); + assertEquals(endString, calResult.getEnd() == null ? null : DATE_TIME_FORMAT.format(calResult.getEnd())); assertEquals(attendee, calResult.getAttendee()); assertEqualOrNaN(latitude, calResult.getLatitude()); assertEqualOrNaN(longitude, calResult.getLongitude()); diff --git a/core/test/src/com/google/zxing/client/result/ParsedReaderResultTestCase.java b/core/test/src/com/google/zxing/client/result/ParsedReaderResultTestCase.java index 0b692265b..e36e987f6 100644 --- a/core/test/src/com/google/zxing/client/result/ParsedReaderResultTestCase.java +++ b/core/test/src/com/google/zxing/client/result/ParsedReaderResultTestCase.java @@ -19,8 +19,12 @@ package com.google.zxing.client.result; import com.google.zxing.BarcodeFormat; import com.google.zxing.Result; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; +import java.util.Locale; +import java.util.TimeZone; + /** * Tests {@link ParsedResult}. * @@ -29,6 +33,12 @@ import org.junit.Test; */ public final class ParsedReaderResultTestCase extends Assert { + @Before + public void setUp() { + Locale.setDefault(Locale.ENGLISH); + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + } + @Test public void testTextType() { doTestResult("", "", ParsedResultType.TEXT); @@ -203,25 +213,25 @@ public final class ParsedReaderResultTestCase extends Assert { // UTC times doTestResult("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504T123456Z\r\n" + "DTEND:20080505T234555Z\r\nEND:VEVENT\r\nEND:VCALENDAR", - "foo\n20080504T123456Z\n20080505T234555Z", + "foo\nMay 4, 2008 12:34:56 PM\nMay 5, 2008 11:45:55 PM", ParsedResultType.CALENDAR); doTestResult("BEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504T123456Z\r\n" + - "DTEND:20080505T234555Z\r\nEND:VEVENT", "foo\n20080504T123456Z\n20080505T234555Z", + "DTEND:20080505T234555Z\r\nEND:VEVENT", "foo\nMay 4, 2008 12:34:56 PM\nMay 5, 2008 11:45:55 PM", ParsedResultType.CALENDAR); // Local times doTestResult("BEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504T123456\r\n" + - "DTEND:20080505T234555\r\nEND:VEVENT", "foo\n20080504T123456\n20080505T234555", + "DTEND:20080505T234555\r\nEND:VEVENT", "foo\nMay 4, 2008 12:34:56 PM\nMay 5, 2008 11:45:55 PM", ParsedResultType.CALENDAR); // Date only (all day event) doTestResult("BEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504\r\n" + - "DTEND:20080505\r\nEND:VEVENT", "foo\n20080504\n20080505", ParsedResultType.CALENDAR); + "DTEND:20080505\r\nEND:VEVENT", "foo\nMay 4, 2008\nMay 5, 2008", ParsedResultType.CALENDAR); // Start time only doTestResult("BEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504T123456Z\r\nEND:VEVENT", - "foo\n20080504T123456Z", ParsedResultType.CALENDAR); + "foo\nMay 4, 2008 12:34:56 PM", ParsedResultType.CALENDAR); doTestResult("BEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504T123456\r\nEND:VEVENT", - "foo\n20080504T123456", ParsedResultType.CALENDAR); + "foo\nMay 4, 2008 12:34:56 PM", ParsedResultType.CALENDAR); doTestResult("BEGIN:VEVENT\r\nSUMMARY:foo\r\nDTSTART:20080504\r\nEND:VEVENT", - "foo\n20080504", ParsedResultType.CALENDAR); + "foo\nMay 4, 2008", ParsedResultType.CALENDAR); doTestResult("BEGIN:VEVENT\r\nDTEND:20080505T\r\nEND:VEVENT", "BEGIN:VEVENT\r\nDTEND:20080505T\r\nEND:VEVENT", ParsedResultType.URI); // Yeah, it's OK that this is thought of as maybe a URI as long as it's not CALENDAR