Having trouble with date picker in phone settings

I need to get the Month/Day/Year from the phone settings and I set date in settings on the phone to 1/1/2021 and I am getting 12/31/2020:

var countdown = Application.getApp().getProperty("CountDownDate");
var infoC=Gregorian.info(new Time.Moment(countdown), Time.FORMAT_SHORT);

var cyear = infoC.year;
var cmonth = infoC.month;
var cday = infoC.day;

System.println(" MyWatchFaceView - onUpdate - countdown:"+countdown+" cmonth:"+cmonth+" cday:"+cday+" cyear:"+cyear);

-------------------------------- output

MyWatchFaceView - onUpdate -  countdown:1609459200 cmonth:12 cday:31 cyear:2020 

  • Bit weird that if no timezone is associated that it picks UTC. I would expect a floating timezone, meaning the timezone is whatever timezone the watch is currently in. 

    To take my argument to its logical conclusion, suppose CIQ date settings worked the way you are suggesting (or my understanding of it):

    - When you select a date of 2021-01-01 using an app settings date picker, this is stored internally as "2021-01-01, midnight (your local timezone)" (converted to a UNIX timestamp.)

    Consider the following scenario:

    - The local time zone is UTC+14:00

    - The user sets of a date of 2021-01-01 in some app settings. Internally this will be stored as 2020-12-31 10:00 UTC (which is the same as 2021-01-01 midnight UTC+14 / local time), in the form of a unix timestamp (which of course has no associated time zone information)

    - The user travels to a UTC-10:00 time zone

    - The app reads the previously stored date which is 2020-12-31 10:00 UTC, or 2020-12-31 0:00 UTC-10 / local time.

    - Now the app has no idea whether the original date was supposed to be 2021-01-01 (in the original time zone) or 2020-12-31 (in the user's current time zone). In either case the local time is midnight, so the app can't use that to "guess". The app doesn't even know what the original time zone was (although it can guess that was either UTC+14 or UTC-10)

    That may very well be the behavior that a manager or end user wants, but I would argue it's probably not what's desired for a date-only picker.

    Or maybe I'm not understanding your suggestion (in that case, my bad). Given that a date is stored as a UNIX timestamp, I only see 2 possibilities tho:

    - (What Garmin does) Store your selected date as "<YOUR DATE>, midnight, UTC time" (converted to UNIX timestamp)

    - (What I outlined above) Store your selected date as "<YOUR DATE>, midnight, local time" (converted to UNIX timestamp)

    (I'm ignoring other possibilities like choosing some other arbitrary fixed time besides midnight, or storing the current time of day, but on the selected date.)

  • Bit weird that if no timezone is associated that it picks UTC. I would expect a floating timezone, meaning the timezone is whatever timezone the watch is currently in. 

    It also occurs to me that you could've just meant "when you read a date that was saved in app settings it should come back as '<that date>, midnight, local time".

    I would agree with that, except the problem is that the date comes back in the same format it was (apparently) saved in, and UNIX timestamps are always relative to UTC.

    So it's not necessarily intuitive, but I think the only thing to do here is to accept that the selected date was stored as a unix timestamp (with the time set as midnight UTC) and interpret it with that in mind.

  • I will say that this is yet another example of something in CIQ that's not necessarily intuitive or well-documented. I know, what a complainer. It says a lot to me that a thread about something that seems unintuitive was resurrected after years with no resolution tho.

  • You made a whole lot of points so I'm going to simplify it a little bit.

    For my day job we have similar issues, we store dates as UTC timestamps but this is wrong. I can see why they once made the this choice, but it makes no sense. And allow me to explain why.

    If we take a datestamp (not timestamp), it should *always* be in a floating timezone. Take a birthday or your marriage day, or date of divorce or death. Pick something that you say, on day X of month Y of year Z this happens. The timezone is irrelevant. Whether you are born on August 15th in Japan or August 15th in the UK it doesn't matter. Once you travel the world, this day is set. It should *not* become 2022-08-15T00:00:00Z in storage, because this makes ones birthday 2022-08-14T20:00:00AST or 2022-08-15T02:00CEST or 2022-08-15T09:00:00JST

    Dates should be timezone-less and thus in a floating timezone. Storage in UTC is only relevant if you want to do math with time, because you can apply easy calculations and than convert it to whatever timezone you are in to figure out when that happens in that timezone. Math with dates differ, because again, it doesn't matter. 5 days plus 5 days is going to be 10 days. Even leap seconds and such have limited (or no) impact on the order of days and higher.

    For those who want to do math with dates, please use higher order first. Meaning first year, month, week and finally days.

    Eg. Take Feb 28th and we add one day and one month to it

    Feb 28th + 1 day == March 1st. March 1st + 1 month == April 1st

    Now we add one month and than a day to it:

    Feb 28th + 1 month == March 28th. March 28th + 1 day == March 29th

    Time is a bit tricky, depending on what you do with time, eg an appointment at 9 am in the morning should be stored in UTC and converted to the relevant timezone(s) of each participant. Same for departure times and arrival times of airplanes, trains etc. Because here timezones mean something. You don't want to be late or early.

    Alarm clocks.. when you want to be woken up at 9 in the morning at your local time, means that it becomes something UTC. Although, if I set an alarm for each morning at 9 am, this should always wake me up at 9 am, regardless of timezone.

    So a date picker.. no timezones. A time picker, depending on the usage.

  • TL;DR I agree dates should be stored and interpreted in a timezone-agnostic manner, in general. One way could be ISO-8601 format (but date only): e.g. “2022-01-01”. *Given* that Garmin chose to store dates as UNIX timestamps, the direction they’ve gone in is the least objectionable route. It would’ve been better if all of this were explicitly documented, and examples were given, along with a note that calls out this confusion, which has evidently come up more than once.

    Just my 2 cents.

    Dates should be timezone-less and thus in a floating timezone.

    Agreed 100%, but the key word for me is “should”.

    So a date picker.. no timezones. A time picker, depending on the usage.

    Yes, I agree 100%, and I made a similar point in my comment. 

    My point was that *given* the decision is made to store dates as UNIX timestamps (*), then logically the only sane way to implement this is to store a given date as “<SELECTED DATE> midnight UTC”, for reasons that we both outlined.

    As a developer of CIQ apps, it’s up to me to understand this (unfortunately it’s not documented explicitly **) and when I *read* a date that was stored in such a way:

    - I use Gregorian.utcInfo(X) to convert it to a year, month and day which is *understood to be timezone-agnostic*. Think of it this way: in this context “utcInfo(X)” does *not* mean “I want X in UTC time”, it means “X was stored as ‘fake UTC time’ (but it’s really timezone-agnostic), please give me the original value of X.”

    - I can then do whatever I want with the year, month and day. I can even take that date and reinterpret it as midnight local time, and convert *that* to a unix timestamp (if I needed to compare to it to other unix timestamps, for example)

    (*) I would guess the main reason for using UNIX timestamps is because they fit in a 32-bit integer, and as I noted above, CIQ and Garmin watches are extremely resource-constrained (even more so in the past). Given the choice of a standard, they chose “seconds since the UNIX epoch”, which is also understandable. (I’m going to ignore known bugs where some timestamps are stored/reported as “seconds since the Garmin epoch”)

    (**) As with many CIQ things, you don’t really know until you try

    Again, to me this entire thread proves to me that the “Garmin way” is often unintuitive and/or poorly documented. Even their own documentation on time-related functions vis-a-vis UTC vs local was incorrect (probably for years). 

    For my day job we have similar issues, we store dates as UTC timestamps but this is wrong. I can see why they once made the this choice, but it makes no sense.

    Yeah, I agree it makes no sense, but counterpoint: in my day job 95% of data exchange is via JSON, and dates are stored as strings with no time zone or time (e.g. “2022-01-01”), which should be perfect, right? Even with the understanding that all dates are meant to refer to the *user’s* local time, we still have UTC vs. local time issues because:

    - Devs didn’t read the documentation for the javascript Date constructor (which states that a string such as “2022-01-01” is interpreted as UTC)

    - Most js date picker libraries work with local date

    - (Perhaps) some libraries actually work with UTC (I didn’t dive into all the issues people had)

    - (Perhaps) there have been misunderstandings about whether stored dates should be interpreted as local or UTC

    - Sometimes even these “timezone-agnostic” date strings are internally converted to something like “2022-01-01T00:00:00” and/or “2022-01-01T00:00:00+0000Z” and again it’s up to the dev to realize that this is really supposed to be interpreted as either “midnight local time” and/or “I don’t care about the time zone.”)

  • To make it even funnier. Pick 1940-05-16T00:00:00Z and convert that to Europe/Amsterdam timezone. It will die because 12 midnight UTC has never happenedin that timezone. The Germans switched at midnight to 1940-05-15T22:20:00+00:20 to 1940-05-16T02:00+02:00

  • IOW, if the only way I’m allowed to communicate date settings is in the form of UTC timestamps (with no associated time zone information), I’ll just have to pretend I’m in the UTC time zone when I read and write date settings. So in this one context, “UTC” effectively means “I don’t care what the time zone is” or “no time zone”.

  • Yes. But you should than also have the ability to ask CIQ in which timezone you are do you can store that to display the correct information. And I recall that's not possible. There was a thread last week or two weeks ago about it?

  • To make it even funnier. Pick 1940-05-16T00:00:00Z and convert that to Europe/Amsterdam timezone. It will die because 12 midnight UTC has never happenedin that timezone. The Germans switched at midnight to 1940-05-15T22:20:00+00:20 to 1940-05-16T02:00+02:00

    That is funny, but IMO the whole discussion is moot since Garmin isn’t going to change things, and like I pointed out, even when you use an actual timezone-agnostic date format, devs still have problems.  ¯\_(ツ)_/¯

    Oh and speaking of JS-related time zone problems, one dev ran into the issue where something like new Date("2022-01-01") is interpreted as UTC instead of local. Instead of using the correct constructor which interprets dates as local (i.e. new Date(2022, 0, 1)), they used a bad stackoverflow answer which suggested something like new Date("2022-01-01") + {TIMEZONE ADJUSTMENT CODE HERE}. The code seemed to work, but there were edge cases related to DST where it gave incorrect results.

    My takeaways from that are:

    - date/time stuff can never be simple enough

    - stackoverflow-driven development can only take you so far

    - good documentation is crucial (reading the js documentation leads you to the correct answer)

  • Yes. But you should than also have the ability to ask CIQ in which timezone you are do you can store that to display the correct information. And I recall that's not possible. There was a thread last week or two weeks ago about it?

    Could you clarify this please?

    I haven’t tried to recreate OP’s specific situation (since there’s enough information in the post and the docs), but my understanding is that if you take the number that was stored in the date setting/property, create a Time.Moment() from that, and pass it to Gregorian.utcInfo(), you will get the correct (timezone-agnostic) year, month and day of month (as well as a time of midnight, but who cares about that.)

    Once you have the year, month and day of month, you should be able to display that however you want, and interpret it with respect to local time, UTC time or some other time zone in any way you want.