Get previous 12months with month end date from given month using Scala - scala

I had an use-case to fetch last 12months with end-date of that month from given date.
For Example if I give input as ('2021-04-23'), the output should be:
output1 = ('2021-04-30', '2021-03-31', '2021-02-28', '2021-01-31', '2020-12-31', '2020-11-30', '2020-10-31', '2020-09-30', '2020-08-31', '2020-07-31', '2020-06-30', '2020-05-31', '2020-04-30')
output2=('2021-04-01','2021-03-01','2021-02-01','2021-01-01','2020-12-01','2020-11-01','2020-10-01','2020-09-01', '2020-08-01','2020-07-01','2020-06-01','2020-05-01','2020-04-01')
I had the code snippet
import java.time.format.DateTimeFormatter
val monthDate = DateTimeFormatter.ofPattern("yyyy-MM")
val start = YearMonth.parse("2021-04", monthDate
val lastTwelveMonths=(0 to 12).map(x => start.minusMonths(x).format(monthDate)).toList
which returns last 12months from current month, Can any one please provide solution which includes end date too for previous 12 months. Thanks

You can use java.time.LocalDate's withDayOfMonth() for what you need:
import java.time.LocalDate
import java.time.format.DateTimeFormatter
val dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val inputDate = LocalDate.parse("2021-04-23")
(0 to 12).map{ n =>
inputDate.minusMonths(n).withDayOfMonth(1).format(dateFormat)
}
// Vector(2021-04-01, 2021-03-01, 2021-02-01, 2021-01-01, 2020-12-01, 2020-11-01, 2020-10-01, 2020-09-01, 2020-08-01, 2020-07-01, 2020-06-01, 2020-05-01, 2020-04-01)
(0 to 12).map{ n =>
val prevDate = inputDate.minusMonths(n)
prevDate.withDayOfMonth(prevDate.lengthOfMonth).format(dateFormat)
}
// Vector(2021-04-30, 2021-03-31, 2021-02-28, 2021-01-31, 2020-12-31, 2020-11-30, 2020-10-31, 2020-09-30, 2020-08-31, 2020-07-31, 2020-06-30, 2020-05-31, 2020-04-30)

Related

Extra milliseconds from Calendar.getInstance.getTimeInMillis

So, I had an innocent little snippet like
import java.util.Calendar
import java.sql.Timestamp
val cal = Calendar.getInstance
cal.set(1968, Calendar.APRIL, 25, 0, 45, 0)
val time = cal.getTimeInMillis
new java.sql.Timestamp(time)
new java.sql.Date(time).formatted("%1$tY-%1$tm-%1$te %1$tH:%1$tM:%1$tS.%1$tL")
and it kept showing me non-zero millisecond values. I was trying to construct a SQL timestamp in a test to compare to the output of a function, so it was a bit of a problem. I couldn't set an exact time -- there's no Calendar.setMillis API.
Or you could use the more recent and up-to-date java.time library.
import java.time.LocalDateTime
import java.time.ZoneId
val time = LocalDateTime.of(1968, 4, 25, 0, 45, 0) //date/time of interest
.atZone(ZoneId.systemDefault()) //this time zone
.toInstant().toEpochMilli() //in milliseconds
new java.sql.Timestamp(time)
//res0: java.sql.Timestamp = 1968-04-25 00:45:00.0
new java.sql.Date(time).formatted("%1$tY-%1$tm-%1$te %1$tH:%1$tM:%1$tS.%1$tL")
//res1: String = 1968-04-25 00:45:00.000
Calendar.getInstance always contains the current time. Subsequently calling 'set' on it overrides the year, month, day, hour, minute and second on it, but not the number of milliseconds. You have to zero those out yourself.
import java.util.Calendar
import java.sql.Timestamp
val cal = Calendar.getInstance
cal.set(1968, Calendar.APRIL, 25, 0, 45, 0)
val millis = cal.getTimeInMillis
val time = millis - millis % 1000
new java.sql.Timestamp(time)
new java.sql.Date(time).formatted("%1$tY-%1$tm-%1$te %1$tH:%1$tM:%1$tS.%1$tL")

How to get Min, Max and Length between dates for each year?

I have an rdd with type RDD[String] as an example here is a part of it as such:
1990,1990-07-08
1994,1994-06-18
1994,1994-06-18
1994,1994-06-22
1994,1994-06-22
1994,1994-06-26
1994,1994-06-26
1954,1954-06-20
2002,2002-06-26
1954,1954-06-23
2002,2002-06-29
1954,1954-06-16
2002,2002-06-30
...
result:
(1982,52)
(2006,64)
(1962,32)
(1966,32)
(1986,52)
(2002,64)
(1994,52)
(1974,38)
(1990,52)
(2010,64)
(1978,38)
(1954,26)
(2014,64)
(1958,35)
(1998,64)
(1970,32)
I group it nicely, but my problem is this v.size part, I do not know to to calculate that length.
Just to put it in perspective, here are expected results:
It is not a mistake that there is two times for 2002. But ignore that.
define date format:
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
and order:
implicit val localDateOrdering: Ordering[LocalDate] = Ordering.by(_.toEpochDay)
create a function that receives "v" and returns MAX(date_of_matching_year) - MIN(date_of_matching_year)) = LENGTH (in days):
def f(v: Iterable[Array[String]]): Int = {
val parsedDates = v.map(LocalDate.parse(_(1), formatter))
parsedDates.max.getDayOfYear - parsedDates.min.getDayOfYear
then replace the v.size with f(v)

DateTime: Difference between Hour and Integer

I have some mistakes, in my code in the 2 lines where a comment above them:
import java.time.temporal.ChronoUnit
import java.time.LocalTime
import scala.concurrent.duration._
val t = LocalTime.now()
def toStart(t: LocalTime) = {
val start = LocalTime.of(9, 0)
val midEnd = LocalTime.of(13, 0)
val midStart = LocalTime.of(14, 0)
val end = LocalTime.of(18, 0)
if (t.isBefore(start)) 0.hours
// if (9 > myHour < 13 ==> myHour + 9 Hours, I wrote: - 9.hours instead of + 4.hours
else if (t.isBefore(midEnd)) t.until(midEnd, ChronoUnit.MILLIS).millis - 9.hours
else if (t.isBefore(midStart)) 4.hours
// if (14 > myHour < 18 Then (myhour - 14) + 4
else if (t.isBefore(end)) t.until(end, ChronoUnit.MILLIS).millis
else 8.hours
}
implicit class formatter(d: FiniteDuration) {
def withMinutes = {
val l = d.toMinutes
s"${l / 60}:${l % 60}"
}
def withSeconds = s"${d.toHours}:${d.toMinutes % 60}:${d.toSeconds % 60}"
}
The test of the function ToStart, is false in these tow cases:
scala> toStart(LocalTime.of(9, 30, 24)).withSeconds
res89: String = -5:-30:-24
scala> toStart(LocalTime.of(12, 30, 32)).withSeconds
res90: String = -8:-30:-32
scala> toStart(LocalTime.of(14, 30, 45)).withSeconds
res92: String = 3:29:15
scala> toStart(LocalTime.of(16, 22, 44)).withSeconds
res93: String = 1:37:16
How can I change my code to find the best result ?
Code should be similar to my answer to you here, but you need to understand what I did. You definitely need to check api calls I used, but I added some additional comments:
import java.time.temporal.ChronoUnit
import java.time.LocalTime
import scala.concurrent.duration._
val t = LocalTime.now()
// start of the day
val start = LocalTime.of(9, 0)
// end of first half
val midEnd = LocalTime.of(13, 0)
// start of second half
val midStart = LocalTime.of(14, 0)
// end of the day
val end = LocalTime.of(18, 0)
// here we define duration of first half a day: diff between start of a day and midEnd (end of first half)
val firstHalf = start.until(midEnd, ChronoUnit.MILLIS).millis
// here we define duration of second half a day: diff between start of second half a day and end of a day
val secondHalf = midStart.until(end, ChronoUnit.MILLIS).millis
def toStart(t: LocalTime) = {
// when checked time is before start of a day
if (t.isBefore(start)) 0.hours
// otherwise when checked time is before end of first half (will be diff between start time and checked time)
else if (t.isBefore(midEnd)) start.until(t, ChronoUnit.MILLIS).millis
// otherwise when checked time is before start of second half (will be duration of first half)
else if (t.isBefore(midStart)) firstHalf
// otherwise when checked time is before end of a day (will be duration of first half + duration of diff between checked time and start of second half)
else if (t.isBefore(end)) firstHalf + midStart.until(t, ChronoUnit.MILLIS).millis
// otherwise sum of durations
else firstHalf + secondHalf
}
// here you can add any specific format for evaluated duration
implicit class formatter(d: FiniteDuration) {
def withMinutes = {
// convert to minutes
val l = d.toMinutes
// format
s"${l / 60}:${l % 60}"
}
}
toStart(t).withMinutes
toStart(LocalTime.of(9, 30)).withMinutes
toStart(LocalTime.of(12, 30)).withMinutes
toStart(LocalTime.of(13, 30)).withMinutes
toStart(LocalTime.of(14, 30)).withMinutes
Spend some time and check java.time api (specifically LocalTime.until). Check FiniteDuration api to understand .millis suffix I used

Difference between UTC Time values scala

I would like to perform difference between UTC current time and a UTC value in scala.
How about the following?
import java.time._
val time1 = Instant.parse("2017-01-01T12:00:00Z")
val time2 = Instant.now()
val diff = Duration.between(time1, time2)
println("Difference is " + diff)
println("or in seconds: " + diff.getSeconds())
Try it here
Further reading:
https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html
https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html
https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html

How to change 12 Hours to 24 Hours using Scala

I want 12 Hours Time format convert into 24 Hours time format, Here I attached my code and I checked this link1,link2 but it return as same time format.
Code
val inTime = "12:15 PM"
val newTimeFormat = new SimpleDateFormat("hh:mm a")
val timeWithDateFormat = newTimeFormat.parse(inTime)
val outputTime = newTimeFormat.format(timeWithDateFormat)
println("Output===========>",outputTime)
Output is:
(Output===========>,12:15 PM)
How can I resolved it.
As you want your output to be in a different format than your input, you will need to use a different formatters for input and output.
Also... 12:15 PM of 12-hour-format is 12:15 of 24-hour-format. So may be you should use a different time for this example (lets use 03:15 PM or 15:15),
val inTime = "03:15 PM"
val inputTimeFormat = new SimpleDateFormat("hh:mm a")
val timeWithDateFormat = inputTimeFormat.parse(inTime)
val outputTimeFormat = new SimpleDateFormat("HH:mm")
val outputTime = outputTimeFormat.format(timeWithDateFormat)
println("Output===========>", outputTime)
Just create new SimpleDateFormat and use it to format your date;
val format = new SimpleDateFormat("HH:mm")
For details you can check documentation;
Customizing Formats