Hot questions for Using Joda-Time in scala

Question:

I'm trying to convert the date time string 10/10/2015 10:00:00 to the seconds since the unix epoch, which is 1444471200. However, weirdly I'm getting back the value 1444467600 which is actually 10/10/2015 09:00:00. Here's my code:

// using "joda-time" % "joda-time" % "2.9",
//       "org.joda" % "joda-convert" % "1.8.1",

import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat

val dt = DateTime.parse(dateTimeString, DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss"))
dt.getMillis / 1000

Where's this hour offset coming from and how can I get rid of it? My local timezone is GMT (which == UTC at the moment anyway)...


Answer:

Apparently, it's not parsing with GMT/UTC. Just add that to your DateTimeFormat.

DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss").withZoneUTC()

Question:

I have 2 dates in the format below where the month is a 3 letter string

1988-Jul-21

2016-Dec-18

How do I calculate the number of years between the dates in the above format?

I was able to calculate the difference between the dates in years when the month is an integer using Joda time like below

val y = Years.yearsBetween(new LocalDate("1988-12-21"), new LocalDate("2016-1-18"))
println( y.getYears)
Output: 27

Answer:

You use a DateTimeFormat to invoke the LocalDate.parse(String, DateTimeFormatter) method. Something like,

val y = Years.yearsBetween(
        LocalDate.parse("1988-Jul-21", DateTimeFormat.forPattern("yyyy-MMM-dd")),
        LocalDate.parse("2016-Dec-18", DateTimeFormat.forPattern("yyyy-MMM-dd")))

Question:

If before Java 8 releases, definitely I will choose nscala-time for my scala play project.

However since Java 8 releases, recommending using Java 8 data and time instead of joda time for Java project.

So how about for Scala project? Should we stick using nscala-time or switch? If using Java 8 date and time, need to use mutable.

Also, which library has good support for play json library?


Answer:

Java 8 time library (java.time) types are immutable; Joda Time actually has some mutable classes for specific use-cases. There is also a Scala wrapper for java.time which can be used together with a backport of java.time for Java 7. I have no experience with Play JSON, but according to the mailing list,

We should consider migrating to the JSR-310 types internally in Play 3.0 and recommending using java.time._ types in the documentation. It seems like the Reads/Writes implementations we have for those are pretty reasonable. We just need to make sure we add support for those types in other parts of the APIs

But, currently at least the implementation in 2.4.2 for java.time.Instant Reads/Writes is buggy and I'm trying to get this fixed. So, maybe you want to join the discussion here: https://groups.google.com/forum/#!topic/play-framework/VFMTGPCW7Hc

so it seems using nscala-time (or Joda directly) makes more sense for now, especially if you use other parts of Play, not just JSON.

Question:

I am trying to cast com.github.nscala_time.time.Imports.DateTime from nscala-time (a wrapper of joda-time) to java.util.Date

activeUntil.toDate()

But I get this error

value toDate is not a member of Option[com.github.nscala_time.time.Imports.DateTime]

Obviuosly is not the right way to do it. Is there a way to do this?

Thank you in advance


Answer:

Apparently activeUntil is an Option[DateTime] not DateTime itself. You can map it to Date and get providing some default value in case Option is empty like this

activeUntil.map(_.toDate).getOrElse(new Date())

I am not sure where did you get activeUntil from, but probably from a method that can fail to give you your DateTime this is why it returned an Option and forced you to handle the case when there is nothing to return.

Question:

I'm adding validation for date options in a Scala form; there are optional date fields that allow a user to search between a specific date/time range, but the second date needs to be after the first date for a valid range.

At the moment this validation works:

val searchForm = Form(
  mapping(
    "ItemID" -> optional(text),
    "fromDate" ->  optional(jodaLocalDate("yyyy-MM-dd:HH:mm:ss")),
    "toDate" -> optional(jodaLocalDate("yyyy-MM-dd:HH:mm:ss")),
    "Class" -> optional(text),
    "Status" -> optional(text),
    "Group" -> optional(text),
    "Area" -> nonEmptyText,
    "Ordered" -> optional(text)
  )(SearchModel.apply)(SearchModel.unapply)
  verifying("Both or no dates must be selected. Date/Time range must be valid.", f => (f.fromDate.isEmpty && f.toDate.isEmpty)||
  ((f.fromDate.isDefined&&f.toDate.isDefined)&&f.fromDate.head.isBefore(f.toDate.head))))

But it only compares the dates and ignores the time section HH:mm:ss.

Is there a way to add time validation too? Should I be using a different validation method?


Answer:

As long as you get the time section from the form, the Date calling .before() would definitely check on the time portion, too.

Try:

def validateDates(fromDate: Option[Date], toDate: Option[Date]): Boolean = {
  if(fromDate.isEmpty || toDate.isEmpty) false 
  else fromDate.get.before(toDate.get)
}

Then:

verifying("Both or no dates must be selected. Date/Time range must be valid.", f => validateDates(f.fromDate, f.toDate))

Edit: Just realised this wouldn't pass if both date fields are empty, so a slight modification to validateDates would fix that:

def validateDates(fromDate: Option[Date], toDate: Option[Date]): Boolean = {
      if(fromDate.isEmpty && toDate.isEmpty) true 
      else if(fromDate.isEmpty || toDate.isEmpty) false 
      else fromDate.get.before(toDate.get)
    }

Question:

As the title describe, if I have a DateTime object in JodaTime:

import org.joda.time.DateTime

val currentDateTime = new DateTime()

the variable currentDateTime should give me the date and time in my local timezone.

How do I get the DateTimeZone of currentDateTime from here?


Answer:

Call the getZone() method:

currentDateTime.getZone()

Question:

I'm trying to utilise some of the JodaTime methods to improve a basic function I was working on.

The premise is that I need to convert times from one to another based on the timezone given.

I have a list of times as a son:

  "name": "A",
  "timezone": "UTC",
  "jodaDate": "2016-01-12T14:33:37.533"
},
{
  "name": "C",
  "timezone": "UTC",
  "jodaDate": "2016-01-21T10:33:37.533"
}

I'm then running these through a function that takes the object that represents each of the above and a 'to' for converting it to another timezone.

Currently I'm only focusing on UTC to ECT

Coordinated Universal Time is 5 hours ahead of Ecuador Time
12:33 Sunday, Coordinated Universal Time (UTC) is
07:33 Sunday, Ecuador Time (ECT)

I pass in "ECT" as the argument and then convert it. The problem is that somehow, someway the ECT is turning into a 'CET' instead. I'm baffled. I'm sure it's something simple but I just cannot locate the error.

The method (including the wonderful printlns...)

val currentTimezone = DateTimeZone.forTimeZone(TimeZone.getTimeZone(timezoneDetails.timezone))
println("Current Timezone from object: " + currentTimezone)

println("arg for converting to: "+to)
val s = DateTimeZone.forTimeZone(TimeZone.getTimeZone(to))
println("arg when converted to timezone: " + s)

val y = timezoneDetails.jodaDate.withZone(s)
println("Was: " + timezoneDetails.jodaDate)
println("Now: " +y)
y

which will yield:

    Current Timezone from object: UTC
arg for converting to: ECT
arg when converted to timezone: CET
Was: 2016-01-12T14:33:37.533Z
Now: 2016-01-12T15:33:37.533+01:00
Current Timezone from object: UTC
arg for converting to: ECT
arg when converted to timezone: CET
Was: 2016-01-21T10:33:37.533Z
Now: 2016-01-21T11:33:37.533+01:00
Current Timezone from object: UTC
arg for converting to: ECT
arg when converted to timezone: CET
Was: 2015-12-27T10:33:37.533Z
Now: 2015-12-27T11:33:37.533+01:00
Current Timezone from object: UTC
arg for converting to: ECT
arg when converted to timezone: CET
Was: 2015-11-23T14:33:37.533Z
Now: 2015-11-23T15:33:37.533+01:00

I imagine the problem to be with val s = DateTimeZone.forTimeZone(TimeZone.getTimeZone(to)) but I don't understand why

any ideas? Thanks in advance!


Answer:

The problem is with TimeZone.getTimeZone(name):

public static void main(String[] args) {
    TimeZone tz = TimeZone.getTimeZone("ECT");
    System.out.println("Zone: " + tz.getDisplayName(Locale.US));
    }

will print out Zone: Central European Time

The documentation says:

Three-letter time zone IDs

For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such as "PST", "CTT", "AST") are also supported. However, their use is deprecated because the same abbreviation is often used for multiple time zones (for example, "CST" could be U.S. "Central Standard Time" and "China Standard Time"), and the Java platform can then only recognize one of them.

Question:

I need to write a function that takes two timestamps and segment the time range in Days, Hours and Seconds in that order. To walk through an example, lets say the input to our function is

val start = 08-01-14 12:30:00 val end = 08-04-14 12:30:00

our function will return

 min ->  (08-01-14 12:30:00, 08-01-14 13:00:00)
 hour ->  (08-01-14 13:00:00, 08-01-14 24:00:00)
 day ->  (08-02-14  00:00:00, 08-03-14 24:00:00)
 hour -> (08-04-14  00:00:00, 08-04-14 12:00:00)
 min ->  (08-04-14 12:00:00, 08-04-14 12:30:00)

I have hand rolled an implementation that works but its a little kludgy, I am looking for a) is there a library that already does that? b) if not, what would be the best way to implement this?


Answer:

I believe Jodatime does support calculating time periods/ranges; http://joda-time.sourceforge.net/apidocs/org/joda/time/Period.html

I have done this before with Jodatime , it's a little bit technical, but as Jodatime is an AWESOME API for everything time-ish in Java all devs should use it - There was rumours of Jodatime replacing Javas old time-apis...

Introduction: http://www.joda.org/joda-time/

EDIT: Here's what you're looking for: http://joda-time.sourceforge.net/apidocs/org/joda/time/Interval.html IF you are using Jodatime interval can calculate the range/interval/period between two time-objects