Sum time in java

Sum two dates in Java

As always, I would recommend the Java 8 date/time APIs or Joda for date/time work, since they are much more powerful and intuitive.

You can add durations and periods to a DateTime object trivially. You can add minutes/seconds/months equally easily.

However, you can’t add two dates directly, since that doesn’t really make sense. This is a powerful illustration of why Joda is a help — it stops you doing stuff that you really shouldn’t be doing.

If you are using the Date object, you can just do:

Date d1 = . Date d2 = . long sum = d1.getTime() + d2.getTime(); Date sumDate = new Date(sum); 

The code uses the .getTime() method that returns the number of milliseconds since the epoch. Needless to say the Date class has a lot of problems and should be avoided when possible.

Do you want to sum other types instead?

Update: for Calendar , I would do the following (based on javadocs):

Calendar c1 = . Calendar c2 = . long sum = c1.getTimeInMillis() + c2.getTimeInMillis(); Calendar sumCalendar = (Calendar)c1.clone(); sumCalendar.setTimeInMillis(sum); 

UPDATED: As Steve stated, this works if the Date you presented here assumes that the second date is with respect to the Java epoch. If you do want to start with year «0», then you need to account for that (by subtracting your epoch time).

Don’t sum the time in millis of the two dates!

Date d1 = new Date(); Date d2 = new Date(); Date dTotal = new Date(d1.getTime() + d2.getTime()); System.out.println(dTotal); // Incorrect! Misses about 1970 years. 

Just clone the Calendar and add the datetime parts one by one.

Calendar c1 = Calendar.getInstance(); Calendar c2 = Calendar.getInstance(); Calendar cTotal = (Calendar) c1.clone(); cTotal.add(Calendar.YEAR, c2.get(Calendar.YEAR)); cTotal.add(Calendar.MONTH, c2.get(Calendar.MONTH) + 1); // Months are zero-based! cTotal.add(Calendar.DATE, c2.get(Calendar.DATE)); cTotal.add(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY)); cTotal.add(Calendar.MINUTE, c2.get(Calendar.MINUTE)); cTotal.add(Calendar.SECOND, c2.get(Calendar.SECOND)); cTotal.add(Calendar.MILLISECOND, c2.get(Calendar.MILLISECOND)); System.out.println(cTotal.getTime()); // Correct! 

Needless to say, JodaTime is smarter and cleaner with this.

tl;dr

LocalDateTime later = LocalDateTime .parse ( "2010-01-14 19:16:17" .replace ( " " , "T" ) ) .plus( Period.parse ( "P10M3D" ) ) .plus( Duration.parse ( "PT1H10M5S" ) ) ; 

ISO 8601

The representation of a span-of-time using the same format as a moment is creating confusion. A span is not at all the same as a moment.

Instead of using YYYY-MM-DD HH-MM-SS format for a span of time, I suggest using the standard ISO 8601 format of PnYnMnDTnHnMnS. In this format, the P marks the beginning (for «Period» presumably) and the T separates the years-month-days portion from the hours-minutes-seconds portion.

  • PT1H30M → One and a half hours.
  • P3Y6M4DT12H30M5S → Three years, six months, four days, twelve hours, thirty minutes, and five seconds.
  • P10M3DT1H10M5S → Your Question’s duration of 0000-10-03 01:10:05 .

java.time

The Question and the other Answers use troublesome old date-time classes now outmoded by the java.time framework built into Java 8 and later. See Oracle Tutorial. Much of the java.time functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

The java.time classes use ISO 8601 formats by default when parsing and generating Strings that represent date-time values.

The Question does not provide any time zone info, so here we use the LocalDateTime class. If we know an offset-from-UTC we would use the OffsetDateTime class, and if even better we knew a time zone, we would use the ZonedDateTime class.

Spans of time in java.time are divided amongst a pair of classes. Years-months-days are represented by the Period class, and hours-minutes-seconds are handled by the Duration class.

Combining these times, we can indeed perform date-time math. Here we add a span of time to an starting date-time to get a resulting date-time. And we do so in very few lines of code. The result is indeed that expected by the Question.

We convert the input strings to canonical ISO 8601 format by replacing the SPACE in the middle with a T .

LocalDateTime ldt = LocalDateTime.parse ( "2010-01-14 19:16:17".replace ( " " , "T" ) ); //"0000-10-03 01:10:05" Period period = Period.parse ( "P10M3D" ); Duration duration = Duration.parse ( "PT1H10M5S" ); LocalDateTime result = ldt.plus ( period ).plus ( duration ); 

Compare to the result expected in the Question.

LocalDateTime expectation = LocalDateTime.parse ( "2010-11-17 20:26:22".replace ( " " , "T" ) ); Boolean isSame = result.equals ( expectation ); 
System.out.println ( "ldt: " + ldt + " + period: " + period + " + duration: " + duration + " is result: " + result + " compared to expectation: " + expectation + " is the same: " + isSame ); 

ldt: 2010-01-14T19:16:17 + period: P10M3D + duration: PT1H10M5S is result: 2010-11-17T20:26:22 compared to expectation: 2010-11-17T20:26:22 is the same: true

Источник

How to sum times in Java?

I would just parse these Strings myself, convert them to
seconds or milliseconds and sum them up. See answer 2 below.

import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; public class Test051 < public static void main(String[] args) throws Exception < String pt = "1970-01-01-"; ArrayListtimestampsList = new ArrayList(); timestampsList.add("01:00:05"); timestampsList.add("01:00:05"); timestampsList.add("10:00:05"); final DateFormat dt = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss"); final Calendar sum = Calendar.getInstance(); sum.setTimeInMillis(0); long tm0 = new SimpleDateFormat("yyyy-MM-dd").parse(pt).getTime(); System.out.println("tm0 = " + tm0); for (final String t : timestampsList) < // System.out.println(dt.parse(pt + t).getTime()); Date x = dt.parse(pt + t); // System.out.println(x.getTime()); sum.add(Calendar.MILLISECOND, (int)x.getTime()); sum.add(Calendar.MILLISECOND, (int)-tm0); >long tm = sum.getTime().getTime(); System.out.println("tm = " + tm); tm = tm / 1000; long hh = tm / 3600; tm %= 3600; long mm = tm / 60; tm %= 60; long ss = tm; System.out.println(format(hh) + ":" + format(mm) + ":" + format(ss)); > private static String format(long s) < if (s < 10) return "0" + s; else return "" + s; >> 
import java.util.ArrayList; public class Test051 < public static void main(String[] args) throws Exception < ArrayListtimestampsList = new ArrayList(); timestampsList.add("01:00:05"); timestampsList.add("01:00:05"); timestampsList.add("10:00:05"); long tm = 0; for (String tmp : timestampsList) < String[] arr = tmp.split(":"); tm += Integer.parseInt(arr[2]); tm += 60 * Integer.parseInt(arr[1]); tm += 3600 * Integer.parseInt(arr[0]); >long hh = tm / 3600; tm %= 3600; long mm = tm / 60; tm %= 60; long ss = tm; System.out.println(format(hh) + ":" + format(mm) + ":" + format(ss)); > private static String format(long s) < if (s < 10) return "0" + s; else return "" + s; >> 
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; public class Test051 < public static void main(String[] args) throws Exception < ArrayListtimestampsList = new ArrayList(); timestampsList.add("01:00:00"); timestampsList.add("02:00:00"); timestampsList.add("03:00:00"); timestampsList.add("04:00:00"); timestampsList.add("02:00:00"); timestampsList.add("04:00:00"); Date dt0 = new SimpleDateFormat("yyyy-MM-dd").parse("1970-01-01"); // Check very carefully the output of this one. System.out.println(dt0.getTime()); final DateFormat dt = new SimpleDateFormat("HH:mm:ss"); final Calendar c = Calendar.getInstance(); c.setTimeInMillis(0); for (final String t : timestampsList) < c.add(Calendar.MILLISECOND, (int) dt.parse(t).getTime()); c.add(Calendar.MILLISECOND, (int)-dt0.getTime()); >// We need to add this back. This is basically the time zone offset. c.add(Calendar.MILLISECOND, (int)dt0.getTime()); System.out.println(c.getTime().getTime()); System.out.println(c.getTimeInMillis()); System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(c.getTime())); System.out.println(new SimpleDateFormat("HH:mm:ss").format(c.getTime())); > > 

Solution 2

If you don’t wanna use peter petrov solution to parse your String yourself, the way to do it with Calendar and SimpleDateFormat is as follow :

List timestampsList = new ArrayList(); timestampsList.add("11:00:00"); timestampsList.add("12:00:00"); timestampsList.add("13:00:00"); final DateFormat dt = new SimpleDateFormat("HH:mm:ss"); final Calendar c = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()); long milliseconds = 0; c.clear(); long startingMS = c.getTimeInMillis(); for (final String t : timestampsList) < milliseconds = milliseconds + (dt.parse(t).getTime() - startingMS); >System.out.println(milliseconds + " milliseconds"); System.out.println(milliseconds / 1000 + " seconds"); System.out.println(milliseconds / 1000 / 60 + " minutes"); System.out.println(milliseconds / 1000 / 60 / 60 + " hours"); 
long startingMS = dt.parse("00:00:00").getTime(); for (final String t : timestampsList)

instead, removing the need for the Calendar . Both result in :

129600000 milliseconds 129600 seconds 2160 minutes 36 hours

Note that you might wanna make the results a double not to miss part of the time.

Solution 3

This is a original code from petrov with some edits made by me. Since it’s quite dificult to discuss in comments providing big snippets of code I posted it as an answer so we can discuss petrov’s other considerations.

public static void somaTempos(final String[] listaTempos) throws ParseException < long tm = 0; final DateFormat dt = new SimpleDateFormat("HH:mm:ss"); final Calendar c = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()); for (String tmp : listaTempos) < c.setTime(dt.parse(tmp)); tm += c.get(Calendar.SECOND) + 60 * c.get(Calendar.MINUTE) + 3600 * c.get(Calendar.HOUR_OF_DAY); >final long l = tm % 3600; System.out.println(SIGRUtil.format(tm / 3600) + ':' + SIGRUtil.format(l / 60) + ':' + SIGRUtil.format(l % 60)); > private static String format(long s) < if (s < 10) < return "0" + s; >return String.valueOf(s); > 

UPDATE: An alternative that also solves my problem:

public static String sumTimes(final String[] timestampList) < long milliseconds = 0; final DateFormat dt = new SimpleDateFormat("HH:mm:ss"); dt.setLenient(false); try < final long timezoneOffset = dt.parse("00:00:00").getTime(); for (final String t: timestampList) < milliseconds += (dt.parse(t).getTime() - timezoneOffset); >> catch (final ParseException e) < throw new BusinessException( "One of the timestamps in the timestamp list cannot be applied to the HH:mm:ss pattern.", e); >((SimpleDateFormat) dt).applyPattern(":mm:ss"); return new StringBuilder(8).append(milliseconds / 3600000).append( dt.format(new Date(milliseconds))).toString(); > 

Actually, the API gives me for free the minutes and the seconds by only reaplying another pattern in the DateFormat after calculating the sum of the time stamps, without forgetting to consider the timezone offset in this calculation, my real problem was how to calculate the number of hours which really is the less dificult part.

Any suggestions of improvements?

Solution 4

If those data input Strings represent durations in hours:minutes:seconds without any date or time-of-day, then the other answers are working much too hard.

Generally, the old java.util.Date and .Calendar classes are notoriously troublesome and should be avoided. Specifically here, those classes have no notion of a span of time. Instead you should be using either Joda-Time or maybe java.time.

Joda-Time

Joda-Time offers three classes to represent a span of time: Interval, Period, and Duration. The first is tied to points along the timeline of the Universe. The other two are not.

The Period and Duration classes are very close cousins. Period is a tuple with a number of years, months, days, hours, minutes, and seconds. Duration is a number of milliseconds with no concept of fields such as days or seconds.

Joda-Time uses the ISO 8601 standard for its defaults in parsing and generating strings. For period/duration time, this means the PnYnMnDTnHnMnS format. The P means «period» and the T is a separator between date and time portions.

Here is some example code in Joda-Time 2.3. Basically a couple of lines: parsePeriod & durationSum.plus seen below.

List durationStrings = new ArrayList(); durationStrings.add( "11:00:00" ); // Number of hours/minutes/seconds. Not time-of-day. durationStrings.add( "12:00:00" ); durationStrings.add( "13:00:00" ); // Expect sum of 36 hours = 11 + 12 + 13. 

Define a formatter to parse those strings. Joda-Time might have such a formatter built-in, but I could not locate it. So I defined one.

PeriodFormatter formatter = new PeriodFormatterBuilder() .appendHours() .appendSeparator( ":" ) .appendMinutes() .appendSeparator( ":" ) .appendSeconds() .toFormatter(); 

Loop the input strings, parsing each one, then adding its duration to the sum.

Duration durationSum = Duration.ZERO; // Initializing to empty amount. Add to this in loop below. for ( String durationString : durationStrings ) < Period period = formatter.parsePeriod( durationString ); Duration duration = period.toStandardDuration(); durationSum = durationSum.plus( duration ); System.out.println( "period: " + period ); System.out.println( "duration: " + duration ); >System.out.println( "durationSum: " + durationSum ); System.out.println( "durationSum as Period: " + durationSum.toPeriod() ); 
period: PT11H duration: PT39600S period: PT12H duration: PT43200S period: PT13H duration: PT46800S durationSum: PT129600S durationSum as Period: PT36H 

Источник

Читайте также:  Закругленные внутрь углы при помощи css
Оцените статью