Scala Joda Time Format Malformed - scala

I can't find many Scala examples with Joda time especially with formatting but here is the error:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "2015-12-11T13:35:45.732-05:00" is malformed at "15-12-11T13:35:45.732-05:00"
Here is the code:
val now = DateTime.now.toString()
val dtf = DateTimeFormat.forPattern("MM-dd-yyyy HH:mm:ss");
val timeForm = dtf.parseDateTime(now)
Most of the java exmaples all seem to work fine with this?

It has nothing to do with Scala. MM-dd-yyyy HH:mm:ss means the string will start with month, then day, etc. (see http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html for the meaning of characters in the patterns). 2015-12-11T13:35:45.732-05:00 obviously doesn't. Either use val now = dtf.printDateTime(DateTime.now) to print current datetime in the same format you are planning to parse, or use the correct format to parse it.

Related

Scala Last Year

I haven't been able to find an answer for this yet for Scala. I am trying to build a variable in scala for last year and last 2 months, and return in YYYY-MM-dd format. Here is what I have built out. Right now instead of the variable returning the expected date formatted the way im requesting the variable just returns the expression. Any thoughts on how I can change my code to present the variable last_year with the last year in a string format?
val last_year=date_sub(current_date()),365)
val last_2=date_sub(current_date()),60)
desired result: last_year= "2021-03-08"
last_2= "2021-01-08"
Here's the same result using the newer java.time library in place of the old and outdated Calendar and SimpleDate options.
val prev_yr = java.time.LocalDate.now().minusYears(1L).toString
Think I have the answer, just in case anyone needs this later on:
val cal:Calendar=Canlendar.getInstance()
val format=new SimpleDateFormat("YYYY-MM-dd")
cal.add(Calendar.Date,-365)
val prev_yr:String=format.format(cal.getTime)
println(prev_yr)

Exact 1 year previous date in Scala

I have a date string like this - 190515(YYMMDD) format. How to get a populate a exact one year previous date from this? ie, Expected Answer - 180515 (YYMMDD). I am using Scala for this.
I have tried the below. But am getting the below exception - Text '190515' could not be parsed
import java.time.LocalDateTime
import java.time.format.{ DateTimeFormatter, DateTimeParseException }
val d1 =LocalDateTime.parse("190515",DateTimeFormatter.ofPattern("yyMMdd"))
d1.minusYears(1)
LocalDateTime is used for points of time having both a date and a time precision. Yours only have a date, so you should be using LocalDate

change the timestamp to UTC format in spark using scala

The question is kind of similar with the problem: Change the timestamp to UTC format in Pyspark
Basically, it is convert timestamp string format ISO8601 with offset to UTC timestamp string(2017-08-01T14:30:00+05:30 -> 2017-08-01T09:00:00+00:00 ) using scala.
I am kind of new to scala/java, I checked spark library which they dont have a way to convert without knowing the timezone, which I dont have a idea of timezone unless (I parse it in ugly way or using java/scala lib?) Can someone help?
UPDATE: The better way to do this: setup timezone session in spark, and use df.cast(DataTypes.TimestampType) to do the timezone shift
org.apache.spark.sql.functions.to_utc_timestamp:
def to_utc_timestamp(ts: Column, tz: String): Column
Given a timestamp like '2017-07-14 02:40:00.0', interprets it as a time in the given time zone, and renders that time as a timestamp in UTC. For example, 'GMT+1' would yield '2017-07-14 01:40:00.0'.
You can use the java.time primitives to parse and convert your timestamp.
scala> import java.time.{OffsetDateTime, ZoneOffset}
import java.time.{OffsetDateTime, ZoneOffset}
scala> val datetime = "2017-08-01T14:30:00+05:30"
datetime: String = 2017-08-01T14:30:00+05:30
scala> OffsetDateTime.parse(datetime).withOffsetSameInstant(ZoneOffset.UTC)
res44: java.time.OffsetDateTime = 2017-08-01T09:00Z

Joda-time parser with instance-local default timezone

Is there an "instance-local" version of Joda's DateTimeZone.setDefault? I'm trying to achieve something like this:
val parser = new ParserWithDefaultTimezone("GMT+1");
parser.parse("1970-01-01 00:00:00").getMillis // -3600000L
parser.parse("1970-01-01 00:00:00 UTC").getMillis // 0L
Without polluting anything global. All I can find in the Joda docs is something that (ironically) modifies global state.
If there is a non-Joda solution, I am interested in that, too.
EDIT: Forgot to mention that if there is no ready-to-use class that does this, I'll settle for: "what is the easiest way to see if a time string contains an explicit timezone?" I can't distinguish between an explicit one and a timezone that Joda set by default.
EDIT 2: I don't have a format string to feed; I'm looking for something that infers the format at runtime.
You can use withZone to alter the date/time zone used:
val fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss ZZZ").withZone(DateTimeZone.forID("Europe/Berlin"))
val date = fmt.parseDateTime(???);
The set-up required to make the time zone optional is a little bit more complicated:
val tz = new DateTimeFormatterBuilder().appendLiteral(" ").appendTimeZoneId().toFormatter()
val fmt = new DateTimeFormatterBuilder()
.append(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
.appendOptional(tz.getParser())
.toFormatter().withZone(DateTimeZone.forID("Europe/Berlin"))
println(fmt.parseDateTime("1970-01-01 12:00:00 UTC"))
println(fmt.parseDateTime("1970-01-01 12:00:00 Europe/Berlin"))
println(fmt.parseDateTime("1970-01-01 12:00:00"))
As long as your remark
I don't have a format string to feed; I'm looking for something that infers the format at runtime.
applies only with respect to the time zone, solution 2 might do what you want. If, on the other hand, you really don't know, in wich format the dates are provided (dd/mm/yyyy vs. mm/dd/yyyy vs. yyyy/mm/dd vs. whatever), then I think you are out of luck: such a conversion would be ambiguous at best. Is 01/03/2015 the 1st of March or the 3rd of January?

How to parse a date with timezone correctly?

I'm trying to convert a string of text into a date with the following code:
//Input String
str = "14/01/26,12:13:13+00"
//Format
format = new java.text.SimpleDateFormat("yy/MM/dd,HH:mm:ssz")
//Conversion
format.parse(str)
But I obtain the following:
Exception: Unparseable date: "14/01/26,12:13:13+00"
How does my format have to be changed in order to parse this date correctly?
+00 is invalid time zone. It should be +0000.
You could add 00 to str and replace z with Z in pattern to use RFC 822 time zone format:
new java.text.SimpleDateFormat("yy/MM/dd,HH:mm:ssZ").parse(str + "00")
// java.util.Date = Sun Jan 26 16:13:13 MSK 2014
java.util.Date (and java.text.SimpleDateFormat) is not the best choice for project. See this answer for some details.
As a bonus DateTimeFormat from Joda-Time allows you to parse your str without modifications:
// I'm using the same pattern with `Z` here
DateTimeFormat.forPattern("yy/MM/dd,HH:mm:ssZ").parseDateTime(str)
// org.joda.time.DateTime = 2014-01-26T16:13:13.000+04:00
If you're looking for "correctness", then don't use SimpleDateFormat!
For one thing, it's not thread safe... and it's silently unsafe, you'll just end up with corrupt dates and no error being thrown. As you're using Scala then it's a fair bet that concurrent programming and thread safety will apply to you.
Use JodaTime, perhaps with one of the Scala wrappers. It gives you some far nicer tools for building date parsers, and generally does the right thing if you simply use the default parser without specifying any format string.