Reputation: 2205
I have a recyclerview in my Android app with many dates. In order to sort data & insert separators between items grouped by month+year, i use following funs:
private fun monthFromDate(date: Date): Int {
val calendar = Calendar.getInstance()
calendar.time = date
return calendar.get(Calendar.MONTH)
}
private fun yearFromDate(date: Date): Int {
val calendar = Calendar.getInstance()
calendar.time = date
return calendar.get(Calendar.YEAR)
}
I think its bad idea always call Calendar.getInstance(). I don't want to introduce a local variable either. (btw all methods like date.month date.year are deprecated)
The question: I have two util.java.Date instances. Let them be equal if both month & year are equal. How can I implement this fun in fast & optimal way?
Upvotes: 2
Views: 10707
Reputation: 86323
java.time
ShaharT in an answer already mentioned Java 8 as an option. Even on Android Java 7 I believe it’s worth considering using JSR-310, the modern Java date and time API also known as java.time
for your task. It came out with Java 8, but you can use it too. It is generally much nicer to work with. It includes a class YearMonth
for representing a year and a month, just what you need, and this saves you from using two functions and instantiating a Calendar
object for each of those two method calls. So I wanted to show you the correct way to make that conversion.
I am sorry that I cannot write Kotlin code. You will have to make do with Java code, and I trust you to adapt. The Java code is:
private ZoneId zone = ZoneId.of("Europe/Moscow");
private YearMonth yearMonthFromDate(Date date) {
ZonedDateTime dateTime = date.toInstant().atZone(zone);
return YearMonth.from(dateTime);
}
Please insert your desired time zone if you didn’t want Europe/Moscow.
Now you are at it, if you go down this avenue, you may also want to consider whether you want Date
objects in you app at all, or you prefer classes from JSR-310. The Date
and Calendar
classes are considered long outmoded.
On my Mac I ran 100 000 Date
objects through the above method in 37 milliseconds. It may not be the same on an average Android device, but I’m not convinced that you need to worry about how fast the conversion is. General rule of thumb is you shouldn’t worry about it until you see a problem in a realistic setting. If not sure, then test in a realistic setting at your earliest convenience.
To use JSR-310 on Android you will need to have the ThreeTenABP (ABP for Android backport). It is all very well and thoroughly explained in this question: How to use ThreeTenABP in Android Project.
Upvotes: 2
Reputation: 7452
It is not very clear, why is Calendar.getInstance() is sub optimal. However, for your requirement, how about coding it like this:
private fun getYearMonth(date: Date): Int {
val calendar = Calendar.getInstance()
calendar.time = date
return calendar.get(Calendar.YEAR) * 100 + calendar.get(Calendar.MONTH)
}
Gives you access to yearMonth in single interger, like 201711
Upvotes: 1
Reputation: 605
Date.getMonth()
although deprecated is fine. Java keeps backward compatability.
If using Java 8, you can do some benchmark of your version Calendar.getInstance().get(Calendar.MONTH)
vs the new LocalDate.ofEpochDay(new Date().getTime()).getMonthValue()
Upvotes: 3