jxstanford
jxstanford

Reputation: 3397

subtracting a DateTime from a DateTime in scala

I'm relatively new to both scala and jodatime, but have been pretty impressed with both. I'm trying to figure out if there is a more elegant way to do some date arithmetic. Here's a method:


private def calcDuration() : String = {
  val p = new Period(calcCloseTime.toInstant.getMillis - calcOpenTime.toInstant.getMillis)
  val s : String = p.getHours.toString + ":" + p.getMinutes.toString + 
      ":" + p.getSeconds.toString
  return s
}

I convert everything to a string because I am putting it into a MongoDB and I'm not sure how to serialize a joda Duration or Period. If someone knows that I would really appreciate the answer.

Anyway, the calcCloseTime and calcOpenTime methods return DateTime objects. Converting them to Instants is the best way I found to get the difference. Is there a better way?

Another side question: When the hours, minutes or seconds are single digit, the resulting string is not zero filled. Is there a straightforward way to make that string look like HH:MM:SS?

Thanks, John

Upvotes: 7

Views: 17170

Answers (3)

Synesso
Synesso

Reputation: 39018

Does this link help?

How do I calculate the difference between two dates?

This question has more than one answer! If you just want the number of whole days between two dates, then you can use the new Days class in version 1.4 of Joda-Time.

Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

This method, and other static methods on the Days class have been designed to operate well with the JDK5 static import facility.

If however you want to calculate the number of days, weeks, months and years between the two dates, then you need a Period By default, this will split the difference between the two datetimes into parts, such as "1 month, 2 weeks, 4 days and 7 hours".

Period p = new Period(startDate, endDate);

You can control which fields get extracted using a PeriodType.

Period p = new Period(startDate, endDate, PeriodType.yearMonthDay());

This example will return not return any weeks or time fields, thus the previous example becomes "1 month and 18 days".

Upvotes: 2

Arjan Blokzijl
Arjan Blokzijl

Reputation: 6888

Period formatting is done by the PeriodFormatter class. You can use a default one, or construct your own using PeriodFormatterBuilder. It may take some more code as you might like to set this builder up properly, but you can use it for example like so:


scala> import org.joda.time._
import org.joda.time._

scala> import org.joda.time.format._
import org.joda.time.format._

scala> val d1 = new DateTime(2010,1,1,10,5,1,0)
d1: org.joda.time.DateTime = 2010-01-01T10:05:01.000+01:00

scala> val d2 = new DateTime(2010,1,1,13,7,2,0)
d2: org.joda.time.DateTime = 2010-01-01T13:07:02.000+01:00

scala> val p = new Period(d1, d2)
p: org.joda.time.Period = PT3H2M1S

scala> val hms = new PeriodFormatterBuilder() minimumPrintedDigits(2) printZeroAlways() appendHours() appendSeparator(":") appendMinutes() appendSuffix(":") appendSeconds() toFormatter
hms: org.joda.time.format.PeriodFormatter = org.joda.time.format.PeriodFormatter@4d2125

scala> hms print p
res0: java.lang.String = 03:02:01

You should perhaps also be aware that day transitions are not taken into account:


scala> val p2 = new Period(new LocalDate(2010,1,1), new LocalDate(2010,1,2))
p2: org.joda.time.Period = P1D

scala> hms print p2                                                         
res1: java.lang.String = 00:00:00

so if you need to hanldes those as well, you would also need to add the required fields (days, weeks, years maybe) to the formatter.

Upvotes: 8

Jon McAuliffe
Jon McAuliffe

Reputation: 3157

You might want to take a look at Jorge Ortiz's wrapper for Joda-Time, scala-time for something that's a bit nicer to work with in Scala.

You should then be able to use something like

(calcOpenTime to calcCloseTime).millis

Upvotes: 7

Related Questions