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));
24:00:00 00:00:00 05:30:00
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)
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
Actually the last one is not weird. Code is setting the timezone for working instead of working2.
SimpleDateFormat working2 = new SimpleDateFormat("hh:mm:ss");
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
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
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
h are used. As far as I know
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
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.
h/H = 12/24 hours
means you will write hh:mm = 12 hours format and HH:mm = 24 hours format