In Scala, suppose I write
val oneDay = 3600L * 24 // seconds in one day
val twoDay = oneDay * 2 // seconds in two days
Is the final value of oneDay (i.e., 86400) computed at runtime or compile-time?
What about the final value of twoDay?
To be sure of the final values, I try to compile your code using:
scalac main.scala -Xprint:all
And, in the last phase, your code turn to be:
final <synthetic> def delayedEndpoint$Main$1: Unit = {
Main.this.oneDay = 86400L;
Main.this.twoDay = Main.this.oneDay().*(2);
()
};
So, the first value is computed at compile-time but the second value will be computed at runtime.
With Scala 3.0 it is possible to use inline (or final as stated by #ghik) to make also the second value computed at compile time.
Yes, 3600L * 24 will be constant-folded and computed in compile time.
As for oneDay * 2, it depends on how oneDay is declared. If it's something like this:
object Constants {
// note the `final` keyword and *no* explicit type
final val oneDay = 3600L * 24
val twoDay = oneDay * 2
}
then references to oneDay will also be seen as constants by the compiler and constant-folded.
Related
I have a 6 digit value from which i have to get the date in scala. For eg if the value is - 119003 then the output should be
1=20 century
19=2019 year
003= january 3
The output should be 2019/01/03
I have tried ti split the value first and then get the date. But i am not sure how to proceed as i am new to scala
I think you'll have to do the century calculations manually. After that you can let the java.time library do all the rest.
import java.time.LocalDate
import java.time.format.DateTimeFormatter
val in = "119003"
val cent = in.head.asDigit + 19
val res = LocalDate.parse(cent+in.tail, DateTimeFormatter.ofPattern("yyyyDDD"))
.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))
//res: String = 2019/01/03
The Date class of Java 1.0 used 1900-based years, so 119 would mean 2019, for example. This use was deprecated already in Java 1.1 more than 20 years ago, so it’s surprising to see it survive into Scala.
When you say 6 digit value, I take it to be a number (not a string).
The answer by jwvh is correct. My variant would be like (sorry about the Java code, please translate yourself):
int value = 119003;
int year1900based = value / 1000;
int dayOfYear = value % 1000;
LocalDate date = LocalDate.ofYearDay(year1900based + 1900, dayOfYear);
System.out.println(date);
2019-01-03
If you’ve got a string, I would slice it into two parts only, 119 and 003 (not three parts as in your comment). Parse each into an int and proceed as above.
If you need 2019/01/03 format in your output, use a DateTimeFormatter for that. Inside your program, do keep the LocalDate, not a String.
In Scala, is it possible to get number of days between XMLGregorianCalendar? I cannot find any methods in this class that gets the range of two dates. If not how are you guys doing it?
Ah I guess not I just went with this instead and it works fine:
val range:Long = (toDate.toGregorianCalendar.getTimeInMillis - fromDate.toGregorianCalendar.getTimeInMillis) / (1000 * 60 * 60 * 24)
I am trying to parse some given date string:
val strDate = "2014-01-01T00:00:00.000999+00:00"
val dateFormatter = forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZ").withOffsetParsed()
val date = parse(strDate, dateFormatter)
but println(date) outputs 2014-01-01T00:00:00.000Z and
dateFormatter.print(date) returns 2014-01-01T00:00:00.000000+00:00.
I don't understand why the parser only gets 3 fraction of second digits instead of 6 as specified. Can someone explain this ?
EDIT: as #Jesper pointed out, the precision is limited to milliseconds.
Open the org.joda.time.base.BaseDateTime class, you'll see that the time is encoded as:
/** The millis from 1970-01-01T00:00:00Z */
private volatile long iMillis;
That the degree of precision you want can be stored via Joda.
The alternative is to use JSR-310.
if you have Java 8, it's already included.
add a dependency to threeten, then backport for older Java versions.
The base class is Instant which has a nanosecond precision, see: https://github.com/ThreeTen/threetenbp/blob/master/src/main/java/org/threeten/bp/Instant.java
Trying to think of a way to subtract 5 minutes from 2 hours.
It doesn't make sense to subtract 5 from 2, because we end up with -3 generic time units, which is useless. But if "hour" is a subtype of "minute", we could convert 2 hours to 120 minutes, and yield 115 minutes, or 1 hour and 55 minutes.
Similarly, if we want to add 5 apples to 5 oranges, we cannot evaluate this in terms of apples, but might expect to end up with 10 fruit.
It seems in the above examples, and generally when using a number as an adjective, the integers need to be parameterized by the type of object they describing. I think it would be very useful if instead of declaring
val hours = 2
val minutes = 5
you could do something like
val hours = 2[Hour]
val minutes = 5[Minute]
val result = hours - minutes
assert (result == 115[Minute])
Does anything like this exist, would it be useful, and is it something that could be implemented?
EDIT: to clarify, the time example above is just a random example I thought up. My question is more whether in general the idea of parameterized Numerics is a useful concept, just as you have parameterized Lists etc. (The answer might be "no", I don't know!)
You can accomplish this by having two classes for Hours and Minutes, along with an implicit conversion function from hours to minutes
trait TimeUnit
case class Hour(val num: Int) extends TimeUnit
case class Minute(val num: Int) extends TimeUnit {
def - (sub: Minute) = Minute(num - sub.num)
}
implicit def hour2Minute(hour: Hour) = Minute(hour.num * 60)
This allows you to do something like
val h = Hour(2) - Minute(30) //returns Minute(90)
You can find some examples for this in the lift framework (spec).
import net.liftweb.utils.TimeHelpers._
3.minutes == 6 * 30.seconds
(Note: it seems you need to have reasonable numbers for correct comparison. Eg. There may be no more than 60 seconds.)
You might try scala-time, which is a wrapper around Joda Time and makes it a bit more idiomatic for Scala, including some DSL to do time period computations, similar to what Brian Agnew suggested in his answer.
For instance,
2.hours + 45.minutes + 10.seconds
creates a Joda Period.
It seems to me a DSL would be of use here. So you could write
2.hours - 5.minutes
and the appropriate conversions would take place to convert 2 hours into a Hours object (value 2) etc.
Lots of resources exist describing Scala's DSL capabilities. e.g. see this from O'Reilly
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
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.
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
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".