Skip to content

Commit dc7d6ac

Browse files
committed
Comments / KDoc
1 parent c7faa34 commit dc7d6ac

File tree

1 file changed

+27
-16
lines changed

1 file changed

+27
-16
lines changed

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

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,33 +24,42 @@ import java.time.format.DateTimeFormatter
2424
import java.time.format.DateTimeParseException
2525
import java.time.temporal.Temporal
2626

27+
/**
28+
* Maps contact events (like birthdays and anniversaries) to vCard properties.
29+
*
30+
* Android stores the events as date/date-time strings, so we have to parse these strings.
31+
* Unfortunately, the format is not specified in the ContactsContract ("as the user entered it"):
32+
* https://developer.android.com/reference/android/provider/ContactsContract.CommonDataKinds.Event?hl=en#START_DATE
33+
*
34+
* At least we know the formats used by AOSP Contacts:
35+
* https://android.googlesource.com/platform/packages/apps/Contacts/+/c326c157541978c180be4e3432327eceb1e66637/src/com/android/contacts/util/CommonDateUtils.java#25
36+
* so we support at least these formats.
37+
*/
2738
object EventHandler : DataRowHandler() {
2839

29-
// CommonDateUtils: https://android.googlesource.com/platform/packages/apps/Contacts/+/c326c157541978c180be4e3432327eceb1e66637/src/com/android/contacts/util/CommonDateUtils.java#25
30-
3140
/**
32-
* Date formats for full date with time. Converts to [OffsetDateTime].
41+
* Date formats for full date with time (taken from Android's CommonDateUtils).
3342
*/
3443
private val fullDateTimeFormats = listOf(
35-
// Provided by Android's CommonDateUtils
3644
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"),
3745
// "yyyy-MM-dd'T'HH:mm:ssXXX"
3846
DateTimeFormatter.ISO_OFFSET_DATE_TIME,
3947
)
4048

4149
/**
42-
* Date format for full date without time. Converts to [LocalDate].
50+
* Date format for full date without time (taken from Android's CommonDateUtils).
4351
*/
4452
private val fullDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd")
4553

4654

4755
override fun forMimeType() = Event.CONTENT_ITEM_TYPE
4856

4957
/**
50-
* Tries to parse a date string into a [Temporal] object using multiple acceptable formats.
51-
* Returns the parsed [Temporal] if successful, or `null` if none of the formats match.
52-
* @param dateString The date string to parse.
53-
* @return If format is:
58+
* Tries to parse a contact event date string into a [Temporal] object using multiple acceptable formats.
59+
*
60+
* @param dateString The contact event date string to parse.
61+
*
62+
* @return The parsed [Temporal] if successful, or `null` if none of the formats match. If format is:
5463
* - `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` or `yyyy-MM-dd'T'HH:mm:ssXXX` ([fullDateTimeFormats]) -> [OffsetDateTime]
5564
* - `yyyy-MM-dd` ([fullDateFormat]) -> [LocalDate]
5665
* - else -> `null`
@@ -77,11 +86,14 @@ object EventHandler : DataRowHandler() {
7786
}
7887

7988
/**
80-
* Tries to parse a date string into a [PartialDate] object.
81-
* Returns the parsed [PartialDate] if successful, or `null` if parsing fails.
89+
* Tries to parse a contact event date string into a [PartialDate] object, covering the cases
90+
* from Android's CommonDateUtils:
91+
*
92+
* - `--MM-dd`
93+
* - `--MM-dd'T'HH:mm:ss.SSS'Z'`
8294
*
83-
* Does some preprocessing to handle 'Z' suffix and strip nanoseconds, both not supported by
84-
* [PartialDate.parse].
95+
* Does some preprocessing to handle the 'Z' suffix and strip nanoseconds
96+
* (both not supported by [PartialDate.parse]).
8597
*
8698
* @param dateString The date string to parse.
8799
* @return The parsed [PartialDate] or `null` if parsing fails.
@@ -94,11 +106,10 @@ object EventHandler : DataRowHandler() {
94106
val withoutZ = if (dateString.endsWith('Z')) {
95107
// 'Z' is not supported for suffix in PartialDate, replace with actual offset
96108
dateString.removeSuffix("Z") + "+00:00"
97-
} else {
109+
} else
98110
dateString
99-
}
100111

101-
// PartialDates.parse() does not accept fractions of seconds, so strip them if present
112+
// PartialDate.parse() does not accept fractions of seconds, so strip them if present
102113
val subSecondsRegex = "\\.\\d+".toRegex() // 2025-12-05T010203.456+00:30
103114
// ^^^^ (number of digits may vary)
104115
val subSecondsMatch = subSecondsRegex.find(withoutZ)

0 commit comments

Comments
 (0)