Extra milliseconds from Calendar.getInstance.getTimeInMillis - scala

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")

Related

Get previous 12months with month end date from given month using 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)

Kotlin: Getting the difference betweeen two dates (now and previous date)

Sorry if similar questions have been asked too many times, but it seems that there's one or more issues with every answer I find.
I have a date in the form of a String: Ex.: "04112005"
This is a date. 4th of November, 2005.
I want to get the difference, in years and days, between the current date and this date.
The code I have so far gets the year and just substracts them:
fun getAlderFraFodselsdato(bDate: String): String {
val bYr: Int = getBirthYearFromBirthDate(bDate)
var cYr: Int = Integer.parseInt(SimpleDateFormat("yyyy").format(Date()))
return (cYr-bYr).toString()
}
However, naturally, this is quite innacurate, since the month and days aren't included.
I've tried several approaches to create Date, LocalDate, SimpleDate etc. objects and using these to calcualate the difference. But for some reason I haven't gotten any of them to work.
I need to create a Date (or similar) object of the current year, month and day. Then I need to create the same object from a string containing say, month and year (""04112005""). Then I need to get the difference between these, in years, months and days.
All hints are appreciated.
I would use java.time.LocalDate for parsing and today along with a java.time.Period that calculates the period between two LocalDates for you.
See this example:
fun main(args: Array<String>) {
// parse the date with a suitable formatter
val from = LocalDate.parse("04112005", DateTimeFormatter.ofPattern("ddMMyyyy"))
// get today's date
val today = LocalDate.now()
// calculate the period between those two
var period = Period.between(from, today)
// and print it in a human-readable way
println("The difference between " + from.format(DateTimeFormatter.ISO_LOCAL_DATE)
+ " and " + today.format(DateTimeFormatter.ISO_LOCAL_DATE) + " is "
+ period.getYears() + " years, " + period.getMonths() + " months and "
+ period.getDays() + " days")
}
The output for a today of 2020-02-21 is
The difference between 2005-11-04 and 2020-02-21 is 14 years, 3 months and 17 days
It Works Below 26 API level
There are too many formates of dates you just enter the format of date and required start date and end date. It will show you result. You just see different date formate hare and here if you need.
tvDifferenceDateResult.text = getDateDifference(
"12 November, 2008",
"31 August, 2021",
"dd MMMM, yyyy")
General method to calculate date difference
fun getDateDifference(fromDate: String, toDate: String, formater: String):String{
val fmt: DateTimeFormatter = DateTimeFormat.forPattern(formater)
val mDate1: DateTime = fmt.parseDateTime(fromDate)
val mDate2: DateTime = fmt.parseDateTime(toDate)
val period = Period(mDate1, mDate2)
// period give us Year, Month, Week and Days
// days are between 0 to 6
// if you want to calculate days not weeks
//you just add 1 and multiply weeks by 7
val mDays:Int = period.days + (period.weeks*7) + 1
return "Year: ${period.years}\nMonth: ${period.months}\nDay: $mDays"
}
For legacy Date functions below api 26 without running desugaring with Gradle plugin 4.0, java.time.* use:
fun getLegacyDateDifference(fromDate: String, toDate: String, formatter: String= "yyyy-MM-dd HH:mm:ss" , locale: Locale = Locale.getDefault()): Map<String, Long> {
val fmt = SimpleDateFormat(formatter, locale)
val bgn = fmt.parse(fromDate)
val end = fmt.parse(toDate)
val milliseconds = end.time - bgn.time
val days = milliseconds / 1000 / 3600 / 24
val hours = milliseconds / 1000 / 3600
val minutes = milliseconds / 1000 / 3600
val seconds = milliseconds / 1000
val weeks = days.div(7)
return mapOf("days" to days, "hours" to hours, "minutes" to minutes, "seconds" to seconds, "weeks" to weeks)
}
The above answers using java.time.* api is much cleaner and accurate though.

Int96Value to Date string

When reading a parquet file (using Scala) I read the timestamp field back as:
Int96Value{Binary{12 constant bytes, [0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0]}}
How can I convert it to a date string?
I did some research for you. The Int96 format is quite specific a seems to be deprecated.
Here is a discussion about converting Int96 to Date.
Based on this, I created following piece of code:
def main(args: Array[String]): Unit = {
import java.util.Date
import org.apache.parquet.example.data.simple.{Int96Value, NanoTime}
import org.apache.parquet.io.api.Binary
val int96Value = new Int96Value(Binary.fromConstantByteArray(Array(0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0)))
val nanoTime = NanoTime.fromInt96(int96Value)
val nanosecondsSinceUnixEpoch = (nanoTime.getJulianDay - 2440588) * (86400 * 1000 * 1000 * 1000) + nanoTime.getTimeOfDayNanos
val date = new Date(nanosecondsSinceUnixEpoch / (1000 * 1000))
println(date)
}
However, it prints Sun Sep 27 17:05:55 CEST 2093. I am not sure, if this is a date, that you expected.
Edit: using Instance as suggested:
val nanosInSecond = 1000 * 1000 * 1000;
val instant = Instant.ofEpochSecond(nanosecondsSinceUnixEpoch / nanosInSecond, nanosecondsSinceUnixEpoch % nanosInSecond)
println(instant) // prints 2093-09-27T15:05:55.933865216Z
java.time supports Julian days.
Credits to ygor for doing the research and finding out how to interpret the 12 bytes of your array.
byte[] int96Bytes = { 0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0 };
// Find Julian day
int julianDay = 0;
int index = int96Bytes.length;
while (index > 8) {
index--;
julianDay <<= 8;
julianDay += int96Bytes[index] & 0xFF;
}
// Find nanos since midday (since Julian days start at midday)
long nanos = 0;
// Continue from the index we got to
while (index > 0) {
index--;
nanos <<= 8;
nanos += int96Bytes[index] & 0xFF;
}
LocalDateTime timestamp = LocalDate.MIN
.with(JulianFields.JULIAN_DAY, julianDay)
.atTime(LocalTime.NOON)
.plusNanos(nanos);
System.out.println("Timestamp: " + timestamp);
This prints:
Timestamp: 2017-10-24T03:01:50
I’m not happy about converting your byte array to an int and a long by hand, but I don’t know Parquet will enough to use the conversions that are probably available there. Use them if you can.
It doesn’t matter which LocalDate we use as starting point since we are changing it to the right Julian day anyway, so I picked LocalDate.MIN just to pick one.
The way I read the documentation, Julian days are always in the local time zone, that is, no time zone is understood, and they always start at midday (not midnight).
Link: Documentation of JulianFields in java.time

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

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