LocalTime

Su Suriya Ravichandran Updated 14 Nov 2026
4 min read ·Lesson 115 of 133

java.time.LocalTime represents a time of day (hours, minutes, seconds, and nanoseconds) with no date and no time zone. It answers questions like "what time does the shop open?" or "when is the daily backup?", not "when exactly did this happen?". Like all java.time classes, it is immutable and thread-safe.

Creating a LocalTime

import java.time.LocalTime;

LocalTime now = LocalTime.now();                  // current time in the default zone
LocalTime open = LocalTime.of(9, 0);              // 09:00
LocalTime precise = LocalTime.of(14, 5, 30);      // 14:05:30
LocalTime parsed = LocalTime.parse("18:45");      // ISO format HH:mm[:ss[.nnnnnnnnn]]
LocalTime fromSeconds = LocalTime.ofSecondOfDay(3_600);   // 01:00

Hours use the 24-hour clock, from 0 to 23. Values outside the valid ranges are rejected:

LocalTime.of(24, 0);    // DateTimeException: Invalid value for HourOfDay (valid values 0 - 23): 24

Constants

LocalTime.MIDNIGHT    // 00:00
LocalTime.NOON        // 12:00
LocalTime.MIN         // 00:00
LocalTime.MAX         // 23:59:59.999999999

toString() omits seconds when they are zero, so LocalTime.of(9, 0) prints 09:00 and LocalTime.of(14, 5, 30) prints 14:05:30.

Reading Fields

LocalTime t = LocalTime.of(14, 5, 30);

t.getHour();          // 14
t.getMinute();        // 5
t.getSecond();        // 30
t.getNano();          // 0
t.toSecondOfDay();    // 50730: seconds since midnight

Arithmetic Wraps Around Midnight

A LocalTime lives on a 24-hour clock face, so arithmetic wraps instead of overflowing into another day:

LocalTime.of(23, 30).plusMinutes(45);    // 00:15
LocalTime.of(0, 15).minusHours(1);       // 23:15

That matches how clocks behave, but the information that a day boundary was crossed is lost. If you need to know the date as well, use LocalDateTime.

The wrap-around also affects loops. A loop such as for (LocalTime t = start; t.isBefore(end); t = t.plusHours(1)) never ends if end is 23:59 and the step jumps past midnight back to 00:00. Loop conditions over LocalTime should be written so that they cannot wrap.

Adjusting and Truncating

LocalTime t = LocalTime.of(14, 5, 30);

t.withMinute(0);                          // 14:00:30
t.withHour(9);                            // 09:05:30
t.truncatedTo(ChronoUnit.HOURS);          // 14:00
t.truncatedTo(ChronoUnit.MINUTES);        // 14:05

Truncating is useful for grouping events by hour or minute, and for removing nanoseconds before display or storage.

Comparing Times

LocalTime a = LocalTime.of(10, 0);
LocalTime b = LocalTime.of(9, 59);

a.isBefore(b);       // false
a.isAfter(b);        // true
a.compareTo(b) > 0;  // true

The comparison is purely within one day: 23:00 is always after 01:00, even if you mean "1 am tomorrow."

Measuring Between Times

ChronoUnit.MINUTES.between(LocalTime.of(9, 15), LocalTime.of(10, 0));   // 45
Duration.between(LocalTime.of(9, 15), LocalTime.of(17, 45));           // PT8H30M
Duration.between(LocalTime.of(22, 0), LocalTime.of(6, 0));             // PT-16H

The last result is negative: from 22:00 back to 06:00 on the same day. For an overnight shift (22:00 to 06:00 the next morning), the correct length is 8 hours, which requires either dates (LocalDateTime) or explicit handling: if the result is negative, add 24 hours.

Duration shift = Duration.between(start, end);
if (shift.isNegative()) shift = shift.plusHours(24);     // PT8H

Formatting

DateTimeFormatter twelveHour = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);
LocalTime.of(18, 45).format(twelveHour);    // "06:45 PM"

Date Formatting has its own lesson.

LocalTime Is Not a Moment

A LocalTime such as 09:00 occurs once every day in every time zone. Storing "the meeting is at 09:00" as a LocalTime alone is fine for recurring rules (the shop opens at 9:00 every day), but not for one specific event, which needs a date and a zone (ZonedDateTime). Combine them when needed:

LocalDate date = LocalDate.of(2026, 11, 20);
LocalDateTime dt = LocalTime.of(9, 0).atDate(date);                 // 2026-11-20T09:00
ZonedDateTime zdt = dt.atZone(ZoneId.of("Asia/Kolkata"));           // a specific moment

Practical Example: Opening Hours and Appointment Slots

A booking page shows whether businesses are open and lists available consultation slots. One business, a pharmacy, is open overnight.

import java.time.*;
import java.util.*;

public class LT {
    record Hours(LocalTime open, LocalTime close) {
        boolean isOpenAt(LocalTime t) {
            if (close.isAfter(open)) {
                return !t.isBefore(open) && t.isBefore(close);       // same-day hours
            }
            return !t.isBefore(open) || t.isBefore(close);           // overnight hours
        }
    }

    static List<LocalTime> slots(LocalTime from, LocalTime to, Duration length) {
        List<LocalTime> out = new ArrayList<>();
        for (LocalTime t = from; !t.plus(length).isAfter(to); t = t.plus(length)) out.add(t);
        return out;
    }

    public static void main(String[] args) {
        Hours cafe = new Hours(LocalTime.of(8, 0), LocalTime.of(22, 0));
        Hours pharmacy = new Hours(LocalTime.of(20, 0), LocalTime.of(6, 0));
        for (LocalTime now : List.of(LocalTime.of(7, 30), LocalTime.of(21, 59), LocalTime.of(22, 0), LocalTime.of(2, 15))) {
            System.out.printf("%s  cafe %-6s pharmacy %s%n", now, cafe.isOpenAt(now) ? "open" : "closed", pharmacy.isOpenAt(now) ? "open" : "closed");
        }
        System.out.println("Consultation slots: " + slots(LocalTime.of(10, 0), LocalTime.of(12, 0), Duration.ofMinutes(25)));
    }
}

Output:

07:30  cafe closed pharmacy closed
21:59  cafe open   pharmacy open
22:00  cafe closed pharmacy open
02:15  cafe closed pharmacy open
Consultation slots: [10:00, 10:25, 10:50, 11:15]

isOpenAt treats the opening time as inclusive and the closing time as exclusive, so at exactly 22:00 the cafe counts as closed. For ordinary hours (close after open), the time must lie between them. For overnight hours (close before open), the business is open if the time is after opening or before closing, which correctly reports the pharmacy open at 02:15. slots adds the slot length repeatedly but only keeps slots that end by the closing time: a fifth slot would start at 11:40 and run past 12:00, so it is excluded. Because from and to are both within the same day and to is well before midnight, the loop cannot wrap around.

0 Comments

Reviewed before they appear

No comments yet.

Java
Java Introduction Java Features Java Syntax Java Comments Java Statements Java Output Java Variables Java Data Types Java Type Casting Java Operators Java Strings Java Numbers Java Math Java Booleans Java User Input Java Conditions Java If Else Java Switch Java While Loop Java For Loop Java Break Java Continue Java Arrays Java Methods Java Parameters Java Return Values Java Scope Java Recursion Install Java Install JDK Java IDEs Java JDK Java JRE Java JVM Java Compiler Java File Compile Java Run Java JShell Basics Java Packages Java OOP Java Classes Java Objects Class Methods Constructors Constructor Overload this Keyword static Keyword final Keyword Encapsulation Inheritance Polymorphism Abstraction Access Modifiers super Keyword Method Overload Method Override Instanceof Operator Nested Classes Inner Classes Anonymous Classes Enums Records Array Basics Array Length Loop Arrays Multidimensional Arrays Array Copy Array Sorting Array Search ArrayList LinkedList HashSet TreeSet HashMap TreeMap Queue Interface Deque Interface Stack Class Iterator List Interface Set Interface Map Interface Collections Class Comparable Comparator Generics Basics Generic Classes Generic Methods Wildcards String Basics String Length String Methods String Concatenation String Compare String Search String Replace String Split String Format StringBuilder StringBuffer Text Blocks Regular Expressions Number Types Integer Class Float Class Double Class BigInteger BigDecimal Math Class Random Numbers Number Format Date Basics LocalDate LocalTime LocalDateTime ZonedDateTime Date Formatting Date Parsing Period Class Duration Class Java Instant Class Java Exception Basics Java try...catch Java Multiple Catch Blocks Java finally Block Java throw Keyword Java throws Keyword Java Checked Exceptions Java Unchecked Exceptions Java Custom Exceptions Java try-with-resources Java Exception Chaining
Ask about this post
AI Ask about this post

Ask questions about LocalTime and get answers drawn from it.

Signed-in readers only.