Reputation: 566
I'm using joda time 2.7 , I need to add several times in LocalTime format , ignoring TimeZone and toDateTimeToday ;
example:
input (String ... times)
01:10 , 01:10 , 01:10 ,
or
01:10 , 01:10 , 01:10 , 01:10 , 01:10 , 01:10
expected output in ( Millis )
03:30
or expected output in ( Millis )
07:00
My ideia
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
static long sumAccumulatedTimes( long... listTimes ){
Duration duration = Duration.ZERO;
DateTimeZone zone = DateTimeZone.getDefault();
DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm");
for (int i = 0; i < listTimes.length; i++) {
duration = duration.plus( listTimes[i] ); // in iteration three, ocurred problems!
}
long convertZone = zone.convertUTCToLocal( duration.getMillis() ); // Adjust TimeZone
System.out.println("Output: " + fmt.print( convertZone ) );
return 0; // ignore !
}
// Call method
DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm");
sumAccumulatedTimes(
fmt.parseMillis("01:10"),
fmt.parseMillis("01:10")//, up to here Ok (02:20 ouput), next inconsitent values
// fmt.parseMillis("01:10") // add three parameters, is ocurred problems
);
EDIT: Update
Solved by @Meno Hochschild
String[] input = { "12:00", "12:10" };
PeriodFormatter parser =
new PeriodFormatterBuilder()
.appendHours().appendLiteral(":")
.appendMinutes().toFormatter();
Period period = Period.ZERO;
for (String s : input) {
period = period.plus(parser.parsePeriod(s));
}
PeriodFormatter printer =
new PeriodFormatterBuilder()
.printZeroAlways().minimumPrintedDigits(2)
//.appendDays().appendLiteral(":") // remove original code
.appendHours().appendLiteral(":")
.appendMinutes().toFormatter();
//System.out.println("duration=" + // remove original code //printer.print(period.normalizedStandard()));
// output: duration=01:00:10
System.out.println("duration="
printer.print(period.normalizedStandard( PeriodType.time() )));
// output: duration= 24:10
Other Soluction, by @Dexter :)
private static String sumAccumulatedTimes( String... times ){
DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm");
DateTimeZone zone = DateTimeZone.getDefault();
PeriodFormatter pformat = new PeriodFormatterBuilder()
.minimumPrintedDigits(2)
.printZeroAlways()
.appendHours()
.appendLiteral(":")
.appendMinutes()
.toFormatter();
long sum = 0;
for ( String time : times ) {
long parseLong = fmt.parseMillis( time );
sum += zone.convertUTCToLocal( parseLong );
}
Period period = new Period( sum );
return period.toString(pformat);
}
Times the sum two solutions work , ignoring time zone without limitation 24 hours
Thank you.
Upvotes: 1
Views: 1133
Reputation: 566
@llya.
Now your code solves the issue ! But in my case it generates me incompatibility issues using this long in other methods JODA .
e.g.
//87600000
static String parseMillisToTextTime( long time ){
DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm");
return fmt.print(time);
} // ouput 21:20
System.out.println( LocalTime.fromMillisOfDay(87600000).toString("HH:mm") );
// output 00:20
LocalTime lt = new LocalTime(87600000);
System.out.println("output: " + lt.toString("HH:mm"));
// output 21:20
For me to change this method have a high burden of maintenance.
If you want to add your solution with these observations?
Upvotes: 0
Reputation: 29693
You can just add millisecond.
static long sumAccumulatedTimes(String ... array)
{
long sum = 0;
for (String time : array)
{
sum += new LocalTime(time).getMillisOfDay();
}
return sum;
}
The result will be the same
UPD
Convert long to string witout Joda API
static String millisToString(long millis)
{
long hours = millis / (1000 * 60 * 60);
long minutes = (millis / (1000 * 60)) % 60;
return hours + ":" + (minutes < 10 ? "0" : "") + minutes;
}
Upvotes: 0
Reputation: 44071
Don't use DateTimeFormatter
to parse durations. That formatter is designed for formatting and parsing points in time and cannot process any time overflow and also tries to mangle any calculated durations with timezone issues (the root cause of your problem). In my timezone "Europe/Berlin", the expression fmt.parseMillis("01:10")
yields 10 minutes only - not one hour and ten minutes.
Use a duration formatter instead. In Joda-Time, this is called PeriodFormatter
:
String[] input = { "01:10", "01:10", "01:10", "01:10", "01:10", "01:10" };
PeriodFormatter pf =
new PeriodFormatterBuilder()
.minimumPrintedDigits(2).printZeroAlways()
.appendHours().appendLiteral(":").appendMinutes().toFormatter();
Period period = Period.ZERO;
for (String s : input) {
period = period.plus(pf.parsePeriod(s));
}
System.out.println("duration=" + pf.print(period.normalizedStandard()));
// output: duration=07:00
Updated after comment of OP (fix for mishandling day overflow):
String[] input = { "12:00", "12:10" };
PeriodFormatter parser =
new PeriodFormatterBuilder()
.appendHours().appendLiteral(":")
.appendMinutes().toFormatter();
Period period = Period.ZERO;
for (String s : input) {
period = period.plus(parser.parsePeriod(s));
}
PeriodFormatter printer =
new PeriodFormatterBuilder()
.printZeroAlways().minimumPrintedDigits(2)
.appendDays().appendLiteral(":")
.appendHours().appendLiteral(":")
.appendMinutes().toFormatter();
System.out.println("duration=" + printer.print(period.normalizedStandard()));
// output: duration=01:00:10
An alternative fix is using the expression period.normalizedStandard(PeriodType.time())
in order to use clock units only.
Upvotes: 1