0

We are defining a microservice that returns a timestamp in the combined date-and-time ISO 8601 format which is returned to our iOS client that's written in Swift. In our client, this is converted to a Date object.

The issue is one of the feeding sources of our microservice represents their date/times as two separate fields which we must combine into the complete ISO format. However, the time portion may be null so we have to substitute in 'T00:00:00Z'.

The problem is we need a way to communicate to the Swift side that the timestamp didn't have an original time value so it should be read in relative to GST, not the local timezone as one would normally do, and it should only ever be displayed in the UI as a date-only.

That said, what is the proper way to flag a Date object as being Date-only? Our current solution is a paired xIsDateOnly boolean on the model, but that just seems verbose. Does the Date object have any such mechanism/indication? I'm guessing not because a date without a time doesn't actually make sense as dates are based on 12am in a particular timezone, usually implied to be the one the user is in.

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
  • I really with there were separate `Date` and `Time` types, and a `DateTime` that combines them into what the current `(NS)Date` is – Alexander Mar 16 '18 at 02:34
  • I have thought that myself, but when you think about it, a date without a time doesn’t make any sense, because at every moment in time, it is actually two separate dates depending on where you are on the globe. That’s why you have to include the time component (and the time zone too, for that matter.) – Mark A. Donohoe Mar 16 '18 at 02:35
  • You can create your own JSONDecoder DateDecodingStrategy to deal with both cases – Leo Dabus Mar 16 '18 at 02:38
  • you can also create a computed property that always returns the full date – Leo Dabus Mar 16 '18 at 02:40
  • But that would just handle the parsing. How would the client know the date has a discardable time component vs an actual, valid one? – Mark A. Donohoe Mar 16 '18 at 02:40
  • If that info is important you should go with a Bool property or simply check if it is nil otherwise just supply what it is missing or just parse it in both cases – Leo Dabus Mar 16 '18 at 02:41
  • https://stackoverflow.com/a/46458771/2303865 – Leo Dabus Mar 16 '18 at 02:41
  • I don't think I'm being clear. From the Swift perspective, there is only one Date field. The backend internally has a date and a time and needs to relay if the time is valid to the client. That's why I'm thinking, like you said, I have to use a second property of type Bool. – Mark A. Donohoe Mar 16 '18 at 02:43
  • @MarqueIV A date without a time does make sense. For example, lots of user content requires associating something with a date, without a time. E.g. my todo list has a list for "today", "tomorrow" and "next week". Those are dates, but they don't represent any particular time. Of course this could be done by getting the last possible instant of time within each day, but that's not as elegant – Alexander Mar 16 '18 at 03:50
  • The problem is that the whole concept of "day" is dependent on current time zone, therefore it makes sense only when converting "date" to a "string". – Sulthan Mar 16 '18 at 12:49
  • Not quite. Think about it… It was 11:50 PM EST on March 15th when I originally wrote this. At that time, 'tomorrow' for me meant March 16 and was in 10 minutes. However at that exact same moment, it was already March 16th in Europe and 'tomorrow' for them meant March 17th and it wasn't for another 19 hours (and 10 minutes.) This is because a date specified without a time actually implies a time relative to your current timezone and 'tomorrow' really means '12AM in this timezone'. The time is always there. You're just not thinking about it. You're thinking locally, but times are globally. – Mark A. Donohoe Mar 16 '18 at 12:50
  • Exactly, @Sulthan! I was editing my comment when you posted that. Everything is relative to a point in time. A 'date' is relative to a time on a clock in your current timezone. 'Tomorrow' really is a point in time. It's just with 24-hour granularity. – Mark A. Donohoe Mar 16 '18 at 12:51
  • @MarqueIV Exactly but you are not talking about datetime, you are talking about their calendar representations. Compare `Date` vs `DateComponents`. – Sulthan Mar 16 '18 at 12:51
  • A date always implies a time if not explicitly specified. If I tell you we have to launch a rocket 'exactly' when the date changes to April 1st, you won't know when to launch. I would have to say 'in this timezone' which then implies 12am in that timezone because there is no such thing as a 'date' without a time. Even if a time isn't specified, it has to be implied or it's ambiguous. – Mark A. Donohoe Mar 16 '18 at 12:53
  • In our case here, we are saying if the time component of the source is missing, we have to imply the date is relative to our local timezone, hence reading in 00:00:00Z relative to GST not local. Otherwise, we read it in relative to our local timezone so the proper timezone offsets are calculated. You *don't* want the offsets calculated without a time specified. If we read 00:00:00Z in relative to our local timezone, our 'date' would be five hours off. That's why if the time isn't 'valid', we have to treat it differently but we still need a `Date` datatype. – Mark A. Donohoe Mar 16 '18 at 12:59

1 Answers1

0

You're right, the Foundation (NS)Date object is really a timestamp, representing a specific moment in time. While it doesn't let you just specify a particular day, it does have the advantage of being the same no matter what calendar is in use.

To represent something like "June 3, 2014", you can use a DateComponents object. This lets you specify month, day, year, etc, without a time of day, relative to a particular calendar.

dpassage
  • 5,423
  • 3
  • 25
  • 53