Difference between java HH:mm and hh:mm on SimpleDateFormat
JavaDateFormatJava Problem Overview
Whats the difference between kk:mm, HH:mm and hh:mm formats ??
SimpleDateFormat broken = new SimpleDateFormat("kk:mm:ss");
broken.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat working = new SimpleDateFormat("HH:mm:ss");
working.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat working2 = new SimpleDateFormat("hh:mm:ss");
working.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println(broken.format(epoch));
System.out.println(working.format(epoch));
System.out.println(working2.format(epoch));
prints:
24:00:00
00:00:00
05:30:00
Java Solutions
Solution 1 - Java
kk: (01-24) will look like 01, 02..24.
HH:(00-23) will look like 00, 01..23.
hh:(01-12 in AM/PM) will look like 01, 02..12.
so the last printout (working2
) is a bit weird. It should say 12:00:00
(edit: if you were setting the working2
timezone and format, which (as kdagli pointed out) you are not)
Solution 2 - Java
Please take a look here
HH is hour in a day (starting from 0 to 23)
hh are hours in am/pm format
kk is hour in day (starting from 1 to 24)
mm is minute in hour
ss are the seconds in a minute
Solution 3 - Java
Actually the last one is not weird. Code is setting the timezone for working instead of working2.
SimpleDateFormat working2 = new SimpleDateFormat("hh:mm:ss");
working.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
kk goes from 1 to 24, HH from 0 to 23 and hh from 1 to 12 (AM/PM).
Fixing this error gives:
24:00:00
00:00:00
01:00:00
Solution 4 - Java
h/H = 12/24 hours means you will write hh:mm = 12 hours format and HH:mm = 24 hours format
Solution 5 - Java
Use the built-in localized formats
If this is for showing a time of day to a user, then in at least 19 out of 20 you don’t need to care about kk
, HH
nor hh
. I suggest that you use something like this:
DateTimeFormatter defaultTimeFormatter
= DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
System.out.format("%s: %s%n",
Locale.getDefault(), LocalTime.MIN.format(defaultTimeFormatter));
The point is that it gives different output in different default locales. For example:
> en_SS: 12:00 AM > fr_BL: 00:00 > ps_AF: 0:00 > es_CO: 12:00 a.m.
The localized formats have been designed to conform with the expectations of different cultures. So they generally give the user a better experience and they save you of writing a format pattern string, which is always error-prone.
I furthermore suggest that you don’t use SimpleDateFormat
. That class is notoriously troublesome and fortunately long outdated. Instead I use java.time, the modern Java date and time API. It is so much nicer to work with.
Four pattern letters for hour: H, h, k and K
Of course if you need to parse a string with a specified format, and also if you have a very specific formatting requirement, it’s good to use a format pattern string. There are actually four different pattern letters to choose from for hour (quoted from the documentation):
Symbol Meaning Presentation Examples
------ ------- ------------ -------
h clock-hour-of-am-pm (1-12) number 12
K hour-of-am-pm (0-11) number 0
k clock-hour-of-day (1-24) number 24
H hour-of-day (0-23) number 0
In practice H
and h
are used. As far as I know k
and K
are not (they may just have been included for the sake of completeness). But let’s just see them all in action:
DateTimeFormatter timeFormatter
= DateTimeFormatter.ofPattern("hh:mm a HH:mm kk:mm KK:mm a", Locale.ENGLISH);
System.out.println(LocalTime.of(0, 0).format(timeFormatter));
System.out.println(LocalTime.of(1, 15).format(timeFormatter));
System.out.println(LocalTime.of(11, 25).format(timeFormatter));
System.out.println(LocalTime.of(12, 35).format(timeFormatter));
System.out.println(LocalTime.of(13, 40).format(timeFormatter));
> 12:00 AM 00:00 24:00 00:00 AM > 01:15 AM 01:15 01:15 01:15 AM > 11:25 AM 11:25 11:25 11:25 AM > 12:35 PM 12:35 12:35 00:35 PM > 01:40 PM 13:40 13:40 01:40 PM
If you don’t want the leading zero, just specify one pattern letter, that is h
instead of hh
or H
instead of HH
. It will still accept two digits when parsing, and if a number to be printed is greater than 9, two digits will still be printed.
Links
- Oracle tutorial: Date Time explaining how to use java.time.
- Documentation of
DateTimeFormatter
.