Reputation: 1191
Oddly I'm having the inverse problem to many similar posts; I'm trying to use JodaTime (on Android) to give me a dd:hh:mm:ss type output and failing miserably. Code is;
public String GetEventTimeString(boolean withMS, int eventTime)
{
Period p = new Period(eventTime, PeriodType.yearMonthDayTime());
if (withMS)
return _formatter_withms.print(p);
else return _formatter_withoutms.print(p);
}
When I use the debugger to halt after p
is set, I see that p itself has the hours value set to 568 and the days value is zero, so I've not posted the code that creates the formatters. eventTime is an int representing elapsed time in ms and has a value of 2045489151 in this case.
In case there's some oddity with the size of the number and the fact it's an int instead of a long, I tried making a new Period(1500000L, PeriodType.yearMonthDayTime())
and got a period of 0 days, 25 hours, 0 minutes and seconds.
Exploring the structure of the iType member of the period, I see an array iTypes containing elements "years", "months" etc. I also see an array iIndices which appears to map types to elements in some other array. Most indices make sense, but the index corresponding to "Days" is -1. So it seems PeriodType.yearMonthDayTime()
isn't doing what I think the docs say it should.
If I try PeriodType.yearWeekDayTime
I get the same result. If I try PeriodType.yearWeekDay
then the three fields are zero with my 25 hour test value. So it's not just the one PeriodType that's misbehaving.
Wondering about the coincidence of getting exactly 25 hours from my fairly arbitrary (picked a number and kept adding zeroes) 1500000ms, I tried 1510000 and got 25h 10m 0s. But neither of those actually makes any sense when you work the conversion manually!
This is on Android, up to date Android Studio 1.3.2, not sure how to tell what version JodaTime I'm using but it's within the last few months and this seems a bit too glaringly obvious to be an obscure bug- more a combination of misunderstanding and digging too deep on my part I think.
Does anyone have any thoughts on what's going on?
Upvotes: 1
Views: 551
Reputation: 44071
Well, Joda-Time says about the normalization of a millisecond-based period:
Creates a period from the given millisecond duration. Only precise fields in the period type will be used. Imprecise fields will not be populated.
Here the question arises: Is the day unit a precise field in context of Joda-Time? No because a day can have 23 or 25 hours when it comes to switching daylight-saving time on/off in many countries (in reality there are even more possibilities like 23.5 hours etc). So the constructor you call does not fill the day-unit-field.
How can you get the desired normalization effect? Just do this recommended approach (no normalization in constructing the period):
long eventTime = 2045489151;
Period p = new Period(eventTime, PeriodType.millis());
System.out.println(p); // PT2045489.151S (no normalization)
System.out.println(p.normalizedStandard(PeriodType.dayTime()));
// P23DT16H11M29.151S
System.out.println(p.normalizedStandard(PeriodType.yearMonthDayTime()));
// P23DT16H11M29.151S ( the same result as one line before, not the best period type)
It is for debate IMHO that the Period
-constructor, you used does a partial normalization. In my opinion either a full normalization using the given period type or no normalization at all (preferred by me - just leaving the milliseconds as millis, but then the second constructor argument is simply silly) would have been a wiser design decision. Interestingly (and confusing, too), the constructor without explicit period type argument does a partial normalization, too. To avoid premature incomplete normalization in constructor, you have to explicitly specify the period type as PeriodType.millis()
. Sorry for your confusion.
Upvotes: 1