Skip to content

Commit b2412e1

Browse files
committed
Added tests for all datetime formats from AOSP
1 parent 76db7d8 commit b2412e1

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

lib/src/main/kotlin/at/bitfire/vcard4android/contactrow/EventHandler.kt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,25 @@ object EventHandler : DataRowHandler() {
6262
override fun handle(values: ContentValues, contact: Contact) {
6363
super.handle(values, contact)
6464

65-
val dateStr = values.getAsString(Event.START_DATE) ?: return
65+
var dateStr = values.getAsString(Event.START_DATE) ?: return
6666
val full: Temporal? = parseStartDate(dateStr)
6767
val partial: PartialDate? = if (full == null) try {
68-
PartialDate.parse(dateStr)
69-
} catch (_: IllegalArgumentException) {
68+
if (dateStr.endsWith('Z')) {
69+
// 'Z' is not supported for suffix in PartialDate, replace with actual offset
70+
dateStr = dateStr.removeSuffix("Z") + "+00:00"
71+
}
72+
73+
val regex = "\\.\\d{3}".toRegex()
74+
if (dateStr.contains(regex)) {
75+
// partial dates do not accept nanoseconds, so strip them if present
76+
dateStr = dateStr.replace(regex, "")
77+
PartialDate.parse(dateStr)
78+
} else {
79+
PartialDate.parse(dateStr)
80+
}
81+
} catch (e: IllegalArgumentException) {
82+
System.err.println("Could not parse partial date: $dateStr")
83+
e.printStackTrace()
7084
null
7185
} else {
7286
null

lib/src/test/kotlin/at/bitfire/vcard4android/contactrow/EventHandlerTest.kt

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,19 @@ import java.time.ZoneOffset
2525
@RunWith(RobolectricTestRunner::class)
2626
class EventHandlerTest {
2727

28+
// Tested date formats are as provided by Android AOSP Contacts App
29+
// https://android.googlesource.com/platform/packages/apps/Contacts/+/refs/tags/android-13.0.0_r49/src/com/android/contacts/util/CommonDateUtils.java
30+
2831
@Test
29-
fun test_parseStartDate_ISO_UTC_DateTime() {
32+
fun test_parseStartDate_ISO_DATE_AND_TIME_FORMAT_DateTime() {
3033
assertEquals(
3134
OffsetDateTime.of(1953, 10, 15, 23, 10, 0, 0, ZoneOffset.UTC),
3235
EventHandler.parseStartDate("1953-10-15T23:10:00Z")
3336
)
3437
}
3538

3639
@Test
37-
fun test_parseStartDate_ISO_Date() {
40+
fun test_parseStartDate_FULL_DATE_FORMAT_Date() {
3841
assertEquals(
3942
LocalDate.of(1953, 10, 15),
4043
EventHandler.parseStartDate("1953-10-15")
@@ -53,7 +56,7 @@ class EventHandlerTest {
5356
}
5457

5558
@Test
56-
fun testStartDate_Full() {
59+
fun testStartDate_FULL_DATE_FORMAT() {
5760
val contact = Contact()
5861
EventHandler.handle(ContentValues().apply {
5962
put(Event.START_DATE, "1984-08-20")
@@ -65,14 +68,39 @@ class EventHandlerTest {
6568
}
6669

6770
@Test
68-
fun testStartDate_Partial() {
71+
fun testStartDate_DATE_AND_TIME_FORMAT() {
72+
val contact = Contact()
73+
EventHandler.handle(ContentValues().apply {
74+
put(Event.START_DATE, "1953-10-15T23:10:12.345Z")
75+
}, contact)
76+
assertEquals(
77+
OffsetDateTime.of(1953, 10, 15, 23, 10, 12, 345_000_000, ZoneOffset.UTC),
78+
contact.customDates[0].property.date
79+
)
80+
}
81+
82+
@Test
83+
fun testStartDate_NO_YEAR_DATE_FORMAT() {
6984
val contact = Contact()
7085
EventHandler.handle(ContentValues().apply {
7186
put(Event.START_DATE, "--08-20")
7287
}, contact)
7388
assertEquals(PartialDate.parse("--0820"), contact.customDates[0].property.partialDate)
7489
}
7590

91+
@Test
92+
fun testStartDate_NO_YEAR_DATE_AND_TIME_FORMAT() {
93+
val contact = Contact()
94+
EventHandler.handle(ContentValues().apply {
95+
put(Event.START_DATE, "--08-20T23:10:12.345Z")
96+
}, contact)
97+
// Note that nanoseconds are stripped in PartialDate
98+
assertEquals(
99+
PartialDate.builder().month(8).date(20).hour(23).minute(10).second(12).offset(ZoneOffset.UTC).build(),
100+
contact.customDates[0].property.partialDate
101+
)
102+
}
103+
76104

77105
@Test
78106
fun testType_Anniversary() {

0 commit comments

Comments
 (0)