jfitbit icon indicating copy to clipboard operation
jfitbit copied to clipboard

Localization and 24-hour clock issues

Open mariuswatz opened this issue 12 years ago • 3 comments
trafficstars

The way that jfitbit currently handles date parsing fails if the current locale is not Locale.US or if the Fitbit user has specified a 24-hour clock for their account. I was able to get around it by changing back to a 12-hour clock and adding Locale.US to the declarations for the various DateFormats, i.e. doing new SimpleDateFormat( "hh:mmaa", Locale.US ) instead of new SimpleDateFormat( "hh:mmaa" );

The 12 vs. 24 hour issue is fixable by checking for the presence of am/pm in the time string from Fitbit, if it's not there then use an alternative 24-hour date format ("HH:mm").

Thanks for posting this, I have been looking for a way to get intraday Fitbit data for a while. I'll be posting some code using jfitbit in the next week or so.

I had to experiment a little to figure out what minimumTimestamp() and maximumTimestamp() should be to get values for a specific day, it seems that 00:00:00/23:59:59 works for the intraday values but will give you wrong daily totals. To get the correct daily totals I used max=00:00:00 on the day for which I want daily totals and min=max-24hrs, is that correct?

mariuswatz avatar Jan 19 '13 12:01 mariuswatz

Thanks for the feedback--I'm happy to hear of someone finding utility in jfitbit.

I've added the US locale to the date formats as well as 24 hour clock support, as reported. Admittedly I was a bit negligent in my assumptions about default localization.

You last point is interesting. Fitbit responses don't contain timezone information, so it's always assume they match your local system's timezone. For daily resolution, so long as 00:00:00 of the day of interest, local time, is included in the timestamp range, the daily aggregate should be returned. Your first intuition should've worked; I'm still at a loss why it only works when setting the max to 00:00:00 of day of, with min going to day before.

Using the following query, I successfully brought down the daily count for 18 Jan 2013 of the local timezone, as expected:

FitbitQuery query = FitbitQuery.create( )
    .minimumTimestamp( new Date( "18 Jan 2013 00:00:00 CST" ) )
    .maximumTimestamp( new Date( "18 Jan 2013 23:59:59 CST" ) )
    .resolution( FitbitResolution.DAILY );

I was able to reproduce your reported issue, however, by moving my query dates to a timezone behind my system's local time. Any additional information you can provide to resolve this would be greatly appreciated.

Best wishes. I'll be interested to hear more of your upcoming project.

claygregory avatar Jan 20 '13 05:01 claygregory

Actually, I was concerned that timezone might be the reason - I'm currently in GMT +1 so that would make a kind of sense. But that would mean that users in different timezones would have to make a different API calls to get the daily totals, and that seems silly. I noticed that in your code you make the timestamps very close to the start and end of the day, but I tried a few different ways before finally using midnight - 24 hours. Funny how maddening time and date operations can be in API work.

I don't usually worry much about Locale etc.. myself, I caught the 24hr clock issue early on but spent quite a bit of time before discovering that the DateFormat objects were failing because they were expecting to parse a localized Norwegian version of the date string. I was debugging what was coming from the API but only by accident did I print out what the DateFormat object was comparing it to.

Anyway, FitBit's unwillingness to share intraday through the regular API is disappointing. They're surely cashing in on the self-tracking geeks, so why not please that demographic and give them what they want? With the API backlash of Twitter and others moving away from open APIs as a perceived asset it'll be interesting to see where companies like FitBit end .

Thanks again for the code, I'll give you a shoutout in an immiment blog post!

mariuswatz avatar Jan 20 '13 13:01 mariuswatz

Oops, my commit yesterday introduced a regression with 12-hour timestamps (I accidentally used "am/pm" check rather than "AM/PM"), so that's fixed now.

I also just changed the query date handling a bit, to maybe resolve the inconsistency you're seeing with daily resolution queries. I no longer locally round the request dates before sending paged requests up to Fitbit, and also removed the local result filtering on daily resolution calls. Hopefully you'll now be able to use min timestamp as day of request rather than the midnight before. As for the upper bound, for single day queries, it's relatively arbitrary now, so long as it's on the same day as the minimum. I changed my system clock to CET to test and seemed to be okay -- I think the internal date rounding was the source of the issue.

I'm hoping a query similar to as follows returns daily for 18 Jan 2013 for you as well, so jfitbit behaves consistently across timezones. If this now works for you, I'll update the README with details so future users now longer need to experiment with dates to find the right combination.

FitbitQuery query = FitbitQuery.create( )
    .minimumTimestamp( new Date( "18 Jan 2013 00:00:00" ) )
    .maximumTimestamp( new Date( "18 Jan 2013 23:59:59" ) ) //arbitrary upper bounds
    .resolution( FitbitResolution.DAILY );

You're absolutely correct, date/time handling always seems to be a frustrating source of issues!

claygregory avatar Jan 21 '13 00:01 claygregory