-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parse ISO 8601 date(time) strings as Instant #312
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #312 +/- ##
============================================
+ Coverage 45.08% 45.42% +0.33%
- Complexity 422 428 +6
============================================
Files 112 113 +1
Lines 3012 3049 +37
Branches 201 203 +2
============================================
+ Hits 1358 1385 +27
- Misses 1511 1521 +10
Partials 143 143
|
This is a good idea. I'll follow this up with a review, but wanted to mention some things in advance. First, what you suggest is exactly how I'm currently doing it in my app using BigBone: try to parse as a "precise" timestamp, then fall back to an "imprecise" one if that fails. This has worked well for me so far - but having the library provide the parsing would of course be better. Second, regarding Mastodon's return values, some of the imprecise values are apparently returned for privacy reasons, and that is probably where the difference in our test data is coming from. The Some endpoints even return something like the "Unix timestamp on midnight of the given day", we might want to deal with that as well, either now or later. We should definitely be fault-tolerant in the different types of values that might be returned by any of the endpoints. Last but not least, I think the details matter when it comes to turning all of them into seemingly precise timestamps/Instants, especially if the original value was invalid, but potentially also when it was just imprecise. For example, one use case of my app is to periodically check the How about returning instances of a data class that contains an |
I like that idea! I will implement that and add another commit here with a proposal. Thanks for your thoughts! Good to see that we apparently have/had the same ideas here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Happy to approve after we've decided on the idea to make information about the actual precision of a returned value (date+time vs. just date) available to consumers one way or the other.
If we do, we might not need nullable fields at least in some cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation for Entity fields that were cheanged to the new PrecisionDateTime type should no longer claim that they are ISO 8601 date or datetime Strings, and/or that they can be null.
Other than this Kdoc change, I'm very happy with how this turned out. Thanks a lot. :)
@bocops I’ve updated the outdated kDocs. I also noticed a few other issues I had not yet noticed before and have updated the PR accordingly:
Done now! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good now! :)
@PattaFeuFeu @bocops I'd like to review this code before it is merged into master. Thx. |
Description
The Mastodon API returns date time properties in quite a lot of method return types / entities.
We parse as many other properties as we can into our own data types so this PR attempts to also parse date (time) strings into instances of
Instant
where possible.This closes #311.
java.time vs kotlinx.time
For a bit I thought about using https://github.com/Kotlin/kotlinx-datetime but decided against it as that would mean a lot of translating from java.time to kotlinx.time and vice versa if consumers of BigBone are using
java.time
only and would like to keep it that way.It would have made the custom (de-)serializer obsolete but for the previously stated reason, I decided against it.
ISO 8601 date time string vs LocalDate string
The
reports
API method have an example with"last_status_at": "2022-08-25"
, i.e., a LocalDate, butendorsements
, also referencingAccount
in the example have"last_status_at": "2019-11-23T07:05:50.682Z"
, i.e. a full ISO 8601 date time at UTC.It wasn’t clear to me if both could always be possible so I opted for a solution where I first try to parse an Instant from an ISO 8601 Instant string and if that fails, I fall back to a
LocalDate
date formatter. If theLocalDate
variant succeeds, I get thatLocalDate
and return anInstant
at the start of that day on a UTC timeline.Default values
I wasn’t sure what a good equivalent of the previous default
""
could be. At first I had implemented it asInstant.ofEpochSecond(0)
but that also didn’t seem quite right: If consumers of BigBone would receive an Instant at 1970-01-01T00:00:00Z, it would seem like a potentially valid value the API returned after a call.For that reason, I have added all values that do not mention “optional“ on their documentation page simple as
: Instant
without a default value supplied.I made one exception here:
Account
doesn’t havecreated_at
as “optional” but we have recently added JSON example files wherecreated_at
is not available, so I put it as nullable, just in case.Decision needed: Should we make allInstant
s nullable, just to have a default value? Should we supply a different, non-null default value? If so: which one?Recent change with 1700787: I have added the concept of “Precision” at the suggestion of @bocops. Instead of directly returning an
Instant
now, we now returnPrecisionDateTime
which can be one ofExactTime
,StartOfDay
,Invalid
, orUnavailable
.The default value is set so
Unavailable
everywhere. When attempting to deserialise the JSON we get from the Mastodon API, we first try to parse anExactTime
, fall back toStartOfDay
on error, and if that also throws a parsing exception, we fall back toInvalid
, passing the exception to make checking what was going wrong easier.Type of Change
(Keep the one that applies, remove the rest)
Instant
orInstant?
PrecisionDateTime
instances.Instant
insteadHow Has This Been Tested?
I’ve updated existing tests for methods with dates in their JSON and I’ve added new tests for happy and unhappy paths of the custom deserializer.
Mandatory Checklist
gradle check
and there were no errors reported