7

When starting from ajava.util.date object: what is the best way getting the hour part as an integer regarding performance?

I have to iterate a few million dates, thus performance matters.

Normally I'd get the hour as follows, but maybe there are better ways?

java.util.Date date;
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int hours = calendar.get(Calendar.HOUR_OF_DAY);
membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • 1
    I guess you're already reusing the `calendar` instance, aren't you? – Thomas Jul 05 '16 at 10:00
  • Day time savings, summer time? – Joop Eggen Jul 05 '16 at 10:02
  • Does it really matter? What performance gain do you expect? Usually the most time is spent in IO anyway... – Ortwin Angermeier Jul 05 '16 at 10:06
  • 4
    in UTC: (date.getTime() % 86400000) / 3600000 – Rustam Jul 05 '16 at 10:06
  • In Java SE, I think this is actually the best way regarding the performance. I'm trying if there's any other to manage dates in Java Embedded but I can't find any. – Mickael Jul 05 '16 at 10:07
  • As Rustam said you could directly calculate the UTC hour from the time millis. If you need any specific timezone you'd have to handle the offsets (general + dst) yourself though. – Thomas Jul 05 '16 at 10:13
  • 1
    I made the test. It seems that Rustam's answer is the fastest. Priyamal's answer is good, it's actually better than basic calendar but slower than brut operation. – Mickael Jul 05 '16 at 10:29
  • @Rustam would you add this as an answer instead a comment? – membersound Jul 05 '16 at 10:37
  • Why do people think that you can just get the hour from the time millis? To do that you have to assume that since the beginning of time every day had 86400 seconds, and every hour had 3600 seconds. Doesn't UTC have leap seconds? – wallenborn Jul 05 '16 at 10:37
  • @wallenborn well, UTC may, but many java implementations ignore this. See http://stackoverflow.com/questions/30984599/how-does-the-oracle-java-jvm-know-a-leap-second-is-occurring for details. – Hulk Jul 05 '16 at 10:59

2 Answers2

8

In UTC:

int hour = (int)(date.getTime() % 86400000) / 3600000;

or

 long hour = (date.getTime() % 86400000) / 3600000;
Priyamal
  • 2,919
  • 2
  • 25
  • 52
Rustam
  • 1,397
  • 1
  • 13
  • 17
  • cast to an `(int)` or assign it to a `long`. doesnt compile. – Priyamal Jul 05 '16 at 10:40
  • i guess this only works in utc and does not respect any timezone and or daylight-savings. you should retrieve timezone-offset and dst-offset of current region before the brute-force-calculation and add the differences afterwards – Christoph-Tobias Schenke Jul 05 '16 at 10:59
  • This solution does not seem to be correct for input before 1970, isn't it? Floor division needed. – Meno Hochschild Jul 05 '16 at 12:00
  • Oh, and I forgot to say: Another big error is lack of timezone offset calculation so resulting hour is only that in UTC, not anywhere else on earth. I suggest to add the actual zone offset to UTC-time. – Meno Hochschild Jul 05 '16 at 15:15
  • No need to make ugly calculations like this - that as other comments mention don't allow for DST. You don't need to re-invent the wheel - use any of the existing date methods that allow to get the hour. It's not going to make a huge difference to performance. – sp_nz Apr 15 '21 at 02:33
6
Date dateInput = new Date();

since calendar starts at 01.01.1970, 01:00. you have to make further modifications to the code.using below approach avoids that so this will performs faster.

dateInput.toInstant().atZone(ZoneId.systemDefault()).getHour();
Priyamal
  • 2,919
  • 2
  • 25
  • 52
  • No need to convert to LocalDateTime, `dateInput.toInstant().atZone(ZoneId.systemDefault()).getHour()` works fine. Or for UTC: `dateInput.toInstant().atOffset(UTC).getHour()`. – assylias Jul 05 '16 at 11:30
  • thanks @assylias i changed the post after seeing your comment. – Priyamal Jul 05 '16 at 11:36
  • @Priyamal I suggest you edit your answer to delete the original part, focus on that last line and add explanation. – Basil Bourque Jul 06 '16 at 07:25