This set of 30 Java Date and Time exercises covers the modern java.time API in depth, from basic date creation to time zone conversions.
You’ll work with LocalDate, LocalTime, LocalDateTime, and Instant, then move into date arithmetic (plusDays(), Period, ChronoUnit), TemporalAdjusters for things like “next Friday,” formatting and parsing with DateTimeFormatter, handling a DateTimeParseException, and finally ZonedDateTime and ZoneOffset for working across time zones.
Each exercise includes a Problem Statement, Purpose, Hint, and a Solution with Explanation that clarifies exactly which java.time class fits the problem and why.
- Also, See: Java Exercises with over 20+ topic-wise sets and 575+ coding questions to practice.
- Practice questions using our Online Java Compiler
+ Table of Contents (30 Exercises)
Table of contents
- Exercise 1: Current Date Without Time
- Exercise 2: Current Time Without Date
- Exercise 3: Combining Date and Time
- Exercise 4: Extracting Date Details
- Exercise 5: Current Timestamp with Instant
- Exercise 6: Midnight for the Current Date
- Exercise 7: Two Weeks From Today
- Exercise 8: Ten Days Before and After Today
- Exercise 9: Adding Hours and Minutes to the Current Time
- Exercise 10: Leap Year Checker
- Exercise 11: Rolling a DateTime Backward
- Exercise 12: Next and Previous Friday
- Exercise 13: Days Between Two Dates
- Exercise 14: Age Calculator with Period
- Exercise 15: Remaining Months in the Year
- Exercise 16: Time Difference with Duration
- Exercise 17: Seconds Since the Unix Epoch
- Exercise 18: Converting a Unix Timestamp
- Exercise 19: Formatting a Date, European Style
- Exercise 20: Formatting with a Descriptive Pattern
- Exercise 21: Parsing a Date String
- Exercise 22: Parsing a Date-Time with an Offset
- Exercise 23: 24-Hour and 12-Hour Time Formats
- Exercise 24: Handling a Malformed Date String
- Exercise 25: Current Time in a Different Time Zone
- Exercise 26: Listing Available Zone IDs
- Exercise 27: Checking for Friday the 13th
- Exercise 28: Listing All Mondays in a Month
- Exercise 29: Month Lengths for a Given Year
- Exercise 30: Time Difference Between Two Cities
Exercise 1: Current Date Without Time
Problem Statement: Write a program to display the current system date without the time component (LocalDate).
Purpose: This exercise introduces LocalDate, the java.time class dedicated purely to calendar dates, with no time or time zone information attached at all.
Given Input: none (the date is read directly from the system clock)
Expected Output (actual value depends on the date you run this on): Today's date: 2026-07-03
▼ Hint
- Use the static factory method
LocalDate.now()rather than a constructor, sinceLocalDatehas no public constructors. - Printing a
LocalDatedirectly automatically calls itstoString(), which formats it asyyyy-MM-dd. - No time zone needs to be specified for a basic system-clock read, since
now()uses the JVM’s default time zone automatically.
▼ Solution & Explanation
Explanation:
LocalDate.now(): A static factory method that reads the system clock and returns today’s date in the JVM’s default time zone, with no time-of-day information at all.LocalDate: Deliberately models only a calendar date, year, month, and day, which keeps it simple for use cases like birthdays or due dates that should never carry a time component.- Default formatting: Printing
todaydirectly relies onLocalDate‘s built-intoString(), which always produces the ISO-8601yyyy-MM-ddformat. - Alternative:
LocalDate.now(ZoneId.of("America/New_York"))would return today’s date as seen in a specific time zone, rather than the JVM’s default one.
Exercise 2: Current Time Without Date
Problem Statement: Write a program to display the current system time without the date component (LocalTime).
Purpose: This exercise introduces LocalTime, the counterpart to LocalDate that models only a time of day, with no attached calendar date or time zone.
Given Input: none (the time is read directly from the system clock)
Expected Output (actual value depends on the moment you run this): Current time: 15:42:07.183451200
▼ Hint
- Use the static factory method
LocalTime.now(). - The default
toString()output includes hours, minutes, seconds, and often nanoseconds, depending on the precision the clock reports. - No date fields are involved at all, unlike
LocalDateTime.
▼ Solution & Explanation
Explanation:
LocalTime.now(): Reads the system clock and returns the current time of day, in the JVM’s default time zone, with no date attached.- Precision: The exact number of digits shown after the seconds varies depending on how much sub-second precision the underlying system clock provides.
- Why no date fields:
LocalTimeis intentionally limited to hour, minute, second, and nanosecond, making it suitable for representing something like a recurring daily alarm time that should not be tied to a specific calendar day. - Alternative:
now.truncatedTo(ChronoUnit.SECONDS)would drop the nanosecond portion, producing a cleanerHH:mm:ssstyle output.
Exercise 3: Combining Date and Time
Problem Statement: Combine a specific local date (e.g., 2026-07-03) and a specific local time (e.g., 14:30:00) into a single LocalDateTime object.
Purpose: This exercise introduces LocalDateTime as the combination of LocalDate and LocalTime, useful whenever both the calendar date and the time of day matter together, such as scheduling an event.
Given Input: LocalDate.of(2026, 7, 3) and LocalTime.of(14, 30, 0)
Expected Output: Combined date-time: 2026-07-03T14:30
▼ Hint
- Create the
LocalDateandLocalTimeseparately withLocalDate.of()andLocalTime.of(). - Use
LocalDateTime.of(date, time)to merge the two into one object. - The printed format uses a
Tto separate the date portion from the time portion, following the ISO-8601 standard.
▼ Solution & Explanation
Explanation:
LocalDate.of(2026, 7, 3): Builds a specific calendar date directly from year, month, and day values, rather than reading the system clock.LocalTime.of(14, 30, 0): Builds a specific time of day from hour, minute, and second values, using 24-hour notation.LocalDateTime.of(date, time): Combines the two separate objects into a singleLocalDateTimerepresenting both the date and the time together.- Trailing seconds omitted: The printed output shows
14:30rather than14:30:00, sinceLocalDateTime‘s default formatting drops the seconds field whenever it is exactly zero.
Exercise 4: Extracting Date Details
Problem Statement: Extract individual details (Year, Month name, Day of the month, and Day of the week) from a given LocalDate object.
Purpose: This exercise practices pulling individual components out of a LocalDate, including converting the raw Month and DayOfWeek enum values into readable, full-word names.
Given Input: LocalDate.of(2026, 7, 3)
Expected Output:
Year: 2026 Month: July Day of month: 3 Day of week: Friday
▼ Hint
- Use
getYear()andgetDayOfMonth()for the two simple integer fields. getMonth()andgetDayOfWeek()return enum values, not strings, so printing them directly would show all-uppercase names likeJULY.- Call
getDisplayName(TextStyle.FULL, Locale.ENGLISH)on those enum values to get a properly capitalized, readable name instead.
▼ Solution & Explanation
Explanation:
date.getYear()anddate.getDayOfMonth(): Return plainintvalues for the year and day-of-month fields.date.getMonth(): Returns aMonthenum constant such asJULY, representing the month independently of any specific year or day.getDisplayName(TextStyle.FULL, Locale.ENGLISH): Converts the enum constant into a properly formatted, human-readable name in the specified language, rather than the raw enum constant name.date.getDayOfWeek(): Returns aDayOfWeekenum constant, calculated automatically from the date itself rather than being stored separately.
Exercise 5: Current Timestamp with Instant
Problem Statement: Get the current timestamp using Instant to represent the time in UTC/GMT.
Purpose: This exercise introduces Instant, which represents a single, unambiguous point on the timeline in UTC, independent of any time zone, making it ideal for timestamps like log entries or event records.
Given Input: none (the timestamp is read directly from the system clock)
Expected Output (actual value depends on the moment you run this): Current UTC timestamp: 2026-07-03T09:15:42.317842Z
▼ Hint
- Use
Instant.now()to capture the current moment in time. - Unlike
LocalDateorLocalTime,Instanthas no concept of a local time zone. It is always expressed in UTC. - The trailing
Zin the printed output is the standard ISO-8601 marker meaning “UTC”.
▼ Solution & Explanation
Explanation:
Instant.now(): Returns the current point in time as measured from the epoch of January 1, 1970, UTC, expressed with nanosecond precision.- Always UTC: An
Instantnever carries a local time zone offset. It always represents the same universal moment, regardless of where the code is running. - Trailing
Z: A standard ISO-8601 suffix indicating the timestamp is in UTC, sometimes referred to as “Zulu time”. - Why this matters:
Instantis the preferred type for machine-to-machine timestamps, since it avoids all ambiguity around time zones and daylight saving changes thatLocalDateTimealone would not resolve.
Exercise 6: Midnight for the Current Date
Problem Statement: Obtain the exact time at midnight (00:00) for the current date.
Purpose: This exercise introduces atStartOfDay(), a convenience method that produces the exact moment a calendar day begins, useful for range queries like “everything that happened today”.
Given Input: none (today’s date is read directly from the system clock)
Expected Output (actual value depends on the date you run this on): Midnight today: 2026-07-03T00:00
▼ Hint
- Get today’s date first with
LocalDate.now(). - Call
atStartOfDay()directly on thatLocalDate, which returns aLocalDateTimewith the time fields all set to zero. - This is a cleaner alternative to manually combining the date with
LocalTime.MIDNIGHT.
▼ Solution & Explanation
Explanation:
today.atStartOfDay(): Combines the givenLocalDatewith a time of exactly00:00:00, returning a completeLocalDateTime.- Why not just use
LocalTime.MIDNIGHTmanually:atStartOfDay()exists as a convenience method specifically because, in time zones that observe daylight saving changes, the true start of a calendar day is not always exactly midnight local time. Using this method delegates that calculation correctly. - Alternative:
today.atStartOfDay(ZoneId.of("America/New_York"))would return aZonedDateTime, accounting for that specific zone’s actual start-of-day rules.
Exercise 7: Two Weeks From Today
Problem Statement: Write a program to calculate what the date will be exactly 2 weeks from today.
Purpose: This exercise introduces date arithmetic through plusWeeks(), one of several convenience methods LocalDate provides for adding a specific unit of time without any manual calendar math.
Given Input: today’s date, for example 2026-07-03
Expected Output (based on the example date above):
Today: 2026-07-03 Two weeks from today: 2026-07-17
▼ Hint
- Get today’s date with
LocalDate.now(). - Call
plusWeeks(2)on it, which correctly handles rolling over into the next month if needed. LocalDateis immutable, soplusWeeks()returns a brand new object rather than modifyingtodayitself.
▼ Solution & Explanation
Explanation:
today.plusWeeks(2): Adds exactly 14 days to the date, automatically rolling over into the next month or year if the calculation crosses that boundary.- Immutability:
plusWeeks()does not modifytodayin place. It returns a newLocalDateinstance, which is why the result must be captured in its own variable. - Correct month rollover: Since
2026-07-03plus 14 days lands on2026-07-17, well within the same month in this example, but the same call handles crossing into August or beyond just as correctly without any extra logic. - Alternative:
today.plusDays(14)would produce the exact same result, since a week is always defined as 7 days.
Exercise 8: Ten Days Before and After Today
Problem Statement: Calculate the exact date that occurred 10 days before today and the date that will occur 10 days after today.
Purpose: This exercise practices both directions of date arithmetic in the same program, using minusDays() and plusDays() side by side.
Given Input: today’s date, for example 2026-07-03
Expected Output (based on the example date above):
10 days before today: 2026-06-23 10 days after today: 2026-07-13
▼ Hint
- Use
minusDays(10)for the past date andplusDays(10)for the future date. - Both methods correctly cross month and year boundaries automatically, since they operate on the underlying calendar rather than doing simple digit arithmetic.
- Call both methods on the same original
todayvalue, since it remains unchanged after each call.
▼ Solution & Explanation
Explanation:
today.minusDays(10): Subtracts 10 days from the date, automatically rolling back into the previous month if needed, as seen here where July 3rd minus 10 days lands in June.today.plusDays(10): Adds 10 days forward, staying within the same month in this particular example.- Both derived from the same
today: SinceLocalDateis immutable, callingminusDays()and thenplusDays()on the same original variable is safe. Neither call affects the valuetodayitself holds. - Correct calendar awareness: These methods account for varying month lengths automatically, so the same logic works correctly near the end of February, April, or any other month without special-case code.
Exercise 9: Adding Hours and Minutes to the Current Time
Problem Statement: Add 5 hours and 30 minutes to the current system time and display the result.
Purpose: This exercise practices time arithmetic with LocalTime, and shows how chained plus...() calls combine cleanly since each one returns a new, updated LocalTime.
Given Input: none (the starting time is read directly from the system clock)
Expected Output (actual values depend on the moment you run this):
Current time: 10:15:22.418732600 Time after adding 5 hours 30 minutes: 15:45:22.418732600
▼ Hint
- Get the current time with
LocalTime.now(). - Chain
plusHours(5)andplusMinutes(30)together, since each call returns a newLocalTimethat the next call can be applied to directly. - If the addition crosses midnight,
LocalTimeautomatically wraps around back to00:00rather than producing an invalid hour value.
▼ Solution & Explanation
Explanation:
now.plusHours(5).plusMinutes(30): Chains two separate additions together, sinceplusHours()returns a newLocalTimethatplusMinutes()is immediately called on.- Immutability: Neither
plusHours()norplusMinutes()changesnowitself, which is whynowstill prints its original, unmodified value afterward. - Midnight wraparound: If the current time were, for example,
21:00, adding 5 hours 30 minutes would correctly wrap past midnight to02:30the next day, thoughLocalTimeitself has no concept of which calendar day that lands on. - Alternative:
now.plus(Duration.ofHours(5).plusMinutes(30))achieves the same result using aDurationobject instead of two chained method calls.
Exercise 10: Leap Year Checker
Problem Statement: Create a program that determines whether a user-inputted year is a leap year using the java.time API.
Purpose: This exercise shows that java.time already includes correct leap year logic built in, avoiding the need to hand-write the traditional divisible-by-4-but-not-100-unless-by-400 rule.
Given Input: year = 2024
Expected Output: 2024 is a leap year: true
▼ Hint
- Read the year from the user with a
Scanner. - Use the static method
Year.isLeap(long year)rather than implementing the leap year rule manually. - The method returns a plain
boolean, ready to print or use directly in further logic.
▼ Solution & Explanation
Explanation:
Year.isLeap(year): A static utility method that applies the full Gregorian leap year rule internally, correctly handling the divisible-by-4, not-divisible-by-100, divisible-by-400 exceptions.scanner.nextInt(): Reads the year as an integer directly from user input, which is then passed straight into the leap year check.2024: Divisible by 4 and not divisible by 100, so it correctly qualifies as a leap year under the standard rule.- Alternative:
LocalDate.of(year, 1, 1).isLeapYear()would produce the same result, sinceLocalDatealso exposes an instance-levelisLeapYear()method built on the same underlying rule.
Exercise 11: Rolling a DateTime Backward
Problem Statement: Roll a given LocalDateTime object backward by 3 years, 2 months, and 15 days.
Purpose: This exercise practices chaining several minus...() calls together on a single LocalDateTime, showing that mixed-unit date arithmetic is just a sequence of individual, well-defined steps.
Given Input: LocalDateTime.of(2026, 7, 3, 14, 30)
Expected Output:
Original: 2026-07-03T14:30 Rolled back: 2023-04-18T14:30
▼ Hint
- Chain
minusYears(),minusMonths(), andminusDays()together on the same object. - Each call returns a new
LocalDateTime, so the next call in the chain applies to the already-adjusted result. - The order of the chained calls does not change the final result here, since years, months, and days are independent units.
▼ Solution & Explanation
Explanation:
original.minusYears(3): Moves the date back to2023-07-03T14:30, adjusting only the year field..minusMonths(2): Applied to that result, moving it back further to2023-05-03T14:30..minusDays(15): Applied last, landing on2023-04-18T14:30, the final rolled-back value.- Immutability: Each step in the chain produces a brand new
LocalDateTimeobject rather than modifying the previous one, which is whyoriginalstill prints its untouched starting value.
Exercise 12: Next and Previous Friday
Problem Statement: Find the date of the next and previous Friday relative to today’s date.
Purpose: This exercise introduces TemporalAdjusters, a set of reusable rules for calculations like “the next occurrence of a weekday” that would otherwise require manual day-of-week arithmetic.
Given Input: today’s date, for example 2026-07-03 (a Friday)
Expected Output (based on the example date above):
Today: 2026-07-03 Next Friday: 2026-07-10 Previous Friday: 2026-06-26
▼ Hint
- Use
TemporalAdjusters.next(DayOfWeek.FRIDAY)andTemporalAdjusters.previous(DayOfWeek.FRIDAY). - Apply an adjuster to a date using the
with()method. next()andprevious()always move strictly forward or backward, even if today itself is already a Friday.
▼ Solution & Explanation
Explanation:
TemporalAdjusters.next(DayOfWeek.FRIDAY): Produces a rule representing “the next Friday strictly after this date,” which is then applied withwith().- Today already being a Friday: Since
next()is strict, it skips today entirely and lands on the following week’s Friday, one week later, rather than returning today’s own date. TemporalAdjusters.previous(DayOfWeek.FRIDAY): Works the same way in reverse, finding the most recent Friday strictly before today.- Alternative:
TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY)andpreviousOrSame(...)would return today’s own date instead of skipping it, if today already matches the target day of week.
Exercise 13: Days Between Two Dates
Problem Statement: Calculate the exact number of days between two specific dates (e.g., your birthday and today).
Purpose: This exercise introduces ChronoUnit, which can measure the distance between two temporal objects in any unit, days in this case, without manual calendar math.
Given Input: birthday = LocalDate.of(1998, 11, 20), compared against today’s date
Expected Output (actual value depends on today’s date when you run this): Days since birthday: 10087
▼ Hint
- Use
ChronoUnit.DAYS.between(startDate, endDate)rather than subtracting the dates manually. - The argument order matters. Passing the earlier date first produces a positive result.
- The result is returned as a
long, since the day count can be very large for dates far apart.
▼ Solution & Explanation
Explanation:
ChronoUnit.DAYS.between(birthday, today): Counts the exact number of whole days between the two dates, correctly accounting for every leap year that falls within the range.- Argument order: Passing
birthdayfirst andtodaysecond produces a positive count, sincetodaycomes afterbirthday. Swapping the order would return the same magnitude as a negative number. - Why not
Periodhere:Periodexpresses a difference as separate years, months, and days, whileChronoUnit.DAYS.between()collapses the entire gap into one single, easily comparable number. - Alternative: The same calculation also works for other units by swapping
DAYSforWEEKS,MONTHS, orYEARS, though those return the count truncated to whole units rather than the precise day count.
Exercise 14: Age Calculator with Period
Problem Statement: Write an age calculator program that accepts a birthdate and outputs the exact age in Years, Months, and Days using Period.
Purpose: This exercise introduces Period, which is specifically designed to break a date difference down into calendar-aware years, months, and days, unlike ChronoUnit, which only measures a single unit at a time.
Given Input: birthDate = LocalDate.of(1998, 11, 20), compared against today’s date
Expected Output (actual value depends on today’s date when you run this): Age: 27 years, 7 months, 13 days
▼ Hint
- Use
Period.between(birthDate, today)rather thanChronoUnit, sincePeriodis the type designed to hold a years-months-days breakdown. - Call
getYears(),getMonths(), andgetDays()on the resultingPeriodto access each component. - The year count only increments once the birthday’s month and day have actually occurred in the current year, which
Periodhandles automatically.
▼ Solution & Explanation
Explanation:
Period.between(birthDate, today): Calculates the calendar-aware difference between the two dates, expressed as whole years, whole remaining months, and whole remaining days.- Why the year count is 27, not 28: Since today falls in July and the birthday is in November, this year’s birthday has not occurred yet, so only 27 full years have actually passed.
age.getMonths()andage.getDays(): Represent the leftover time past the most recent full year, calculated the same way a person would count “years old, plus a few months and days” by hand.- Why not
ChronoUnit.DAYShere: A single total day count would not distinguish “27 years and a bit” from any other combination of years, months, and days that add up to the same number of total days, which is exactly the breakdown this exercise asks for.
Exercise 15: Remaining Months in the Year
Problem Statement: Calculate the remaining months left in the current calendar year.
Purpose: This exercise practices reading the numeric month value from a date and using simple arithmetic against the fixed value 12 to figure out how much of the year remains.
Given Input: today’s date, for example 2026-07-03
Expected Output (based on the example date above):
Current month: JULY Months remaining in 2026: 5
▼ Hint
- Use
getMonthValue()to get the current month as a plainintfrom 1 to 12. - Subtract that value from 12 to find how many months remain, including the possibility of 0 if it is already December.
- Use
getYear()to print which year the remaining month count applies to.
▼ Solution & Explanation
Explanation:
today.getMonthValue(): Returns the current month as a plain integer, where January is 1 and December is 12.Month.DECEMBER.getValue(): Returns 12, used here instead of a hardcoded literal to make the intent, “the last month of the year”, explicit in the code.today.getMonth(): Printed directly, this shows the rawMonthenum constant in all capitals, such asJULY, rather than a formatted display name.- Boundary case: If
todayfell in December,currentMonthwould equal 12, makingremainingMonthscorrectly evaluate to 0.
Exercise 16: Time Difference with Duration
Problem Statement: Compute the total difference between two LocalTime objects in Hours, Minutes, and Seconds using Duration.
Purpose: This exercise introduces Duration, the time-based counterpart to Period, used for measuring a span of time in hours, minutes, and seconds rather than years, months, and days.
Given Input: start = LocalTime.of(9, 15, 0), end = LocalTime.of(17, 45, 30)
Expected Output: Difference: 8 hours, 30 minutes, 30 seconds
▼ Hint
- Use
Duration.between(start, end)to get the total elapsed time as one combined object. toHours()andtoMinutes()return totals in that single unit, not a clean breakdown, so you will need the modulo operator%to isolate the leftover minutes and seconds.getSeconds()returns the duration’s total length in seconds, useful for extracting the final seconds component with% 60.
▼ Solution & Explanation
Explanation:
Duration.between(start, end): Captures the total elapsed time between the twoLocalTimevalues as a singleDurationobject, internally stored as a total number of seconds and nanoseconds.duration.toHours(): Returns the whole number of hours contained in the duration, truncating any leftover minutes or seconds.duration.toMinutes() % 60:toMinutes()alone would return the total duration in minutes, 510 in this case, so the% 60isolates just the leftover minutes beyond the full hours already counted.duration.getSeconds() % 60: Similarly isolates the leftover seconds beyond the full minutes already accounted for.
Exercise 17: Seconds Since the Unix Epoch
Problem Statement: Find the total number of seconds that have elapsed since the Unix Epoch (January 1, 1970) up to the current moment.
Purpose: This exercise shows how Instant connects directly to the Unix timestamp format widely used in APIs, databases, and other programming languages.
Given Input: none (the current moment is read directly from the system clock)
Expected Output (actual value depends on the moment you run this): Seconds since Unix Epoch: 1783246542
▼ Hint
- Get the current instant with
Instant.now(). - Call
getEpochSecond()on it to retrieve the whole number of seconds since1970-01-01T00:00:00Z. - This value only ever grows, and it is the same underlying timestamp format used across most systems and languages.
▼ Solution & Explanation
Explanation:
Instant.now(): Captures the current moment as anInstant, internally represented as a count of seconds and nanoseconds relative to the epoch.now.getEpochSecond(): Extracts just the whole-seconds portion of that internal representation, discarding the nanosecond fraction.- Why this number is useful: A Unix timestamp is a single, unambiguous integer that is easy to store, compare, and transmit between systems, which is why so many APIs and databases use it as their default timestamp format.
- Alternative:
now.toEpochMilli()returns the same underlying value with millisecond precision instead, which is the format many JavaScript-based systems expect.
Exercise 18: Converting a Unix Timestamp
Problem Statement: Convert a raw Unix timestamp (e.g., 1719924800) back into a readable LocalDateTime.
Purpose: This exercise is the reverse of the previous one, showing how a raw numeric timestamp can be turned back into a structured, human-readable date and time.
Given Input: unixTimestamp = 1719924800L
Expected Output: Converted date-time: 2024-07-02T12:53:20
▼ Hint
- Use
Instant.ofEpochSecond(unixTimestamp)to turn the raw number back into anInstant. - An
Instantalone has no notion of a calendar date or time zone, so it needs to be combined with one to produce aLocalDateTime. - Use
LocalDateTime.ofInstant(instant, zoneId), passingZoneId.of("UTC")to interpret the timestamp in UTC.
▼ Solution & Explanation
Explanation:
Instant.ofEpochSecond(unixTimestamp): Reconstructs the exact universal moment the raw number represents, the reverse operation ofgetEpochSecond()from the previous exercise.ZoneId.of("UTC"): Specifies which time zone to interpret the instant in when converting it into calendar fields. Since Unix timestamps are inherently UTC-based, using UTC here keeps the conversion accurate.LocalDateTime.ofInstant(instant, zoneId): Combines the universal instant with the chosen time zone to produce a readable calendar date and time.- Different zone, different result: Passing a different
ZoneId, such asZoneId.of("America/New_York"), would produce a different local date and time from the exact same underlying instant.
Exercise 19: Formatting a Date, European Style
Problem Statement: Format the current date into the standard European format: dd/MM/yyyy.
Purpose: This exercise introduces DateTimeFormatter, which controls how a date is rendered as text, independent of the default ISO format that printing a LocalDate directly produces.
Given Input: today’s date, for example 2026-07-03
Expected Output (based on the example date above): Formatted date: 03/07/2026
▼ Hint
- Build a
DateTimeFormatterwithDateTimeFormatter.ofPattern("dd/MM/yyyy"). - Lowercase
ddandyyyyrepresent day and year, while uppercaseMMrepresents month, since lowercasemmwould mean minutes instead. - Call
format()on theLocalDate, passing in the formatter, to get the styled string.
▼ Solution & Explanation
Explanation:
DateTimeFormatter.ofPattern("dd/MM/yyyy"): Defines a custom text layout using pattern letters, whereddis the zero-padded day,MMis the zero-padded month, andyyyyis the four-digit year.- Case sensitivity matters:
MM(uppercase) means month, whilemm(lowercase) means minutes. Mixing these up is a common source of formatting bugs. today.format(formatter): Applies the pattern to the date, producing a plainStringlaid out exactly according to the formatter’s rules.- Reusability: The same
formatterinstance can be reused to format any number of differentLocalDatevalues consistently, rather than building a new formatter each time.
Exercise 20: Formatting with a Descriptive Pattern
Problem Statement: Print the current date and time using a descriptive textual pattern, for example: Friday, 03 July 2026 03:45 PM.
Purpose: This exercise builds on the previous one with a richer pattern, combining full weekday and month names with a 12-hour clock and an AM/PM marker.
Given Input: the current date and time, for example 2026-07-03T15:45
Expected Output (based on the example date and time above): Formatted: Friday, 03 July 2026 03:45 PM
▼ Hint
- Use
EEEEfor the full weekday name andMMMMfor the full month name. - Use lowercase
hhfor the 12-hour clock hour, paired with a literalafor the AM/PM marker. - Pass a
Locale, such asLocale.ENGLISH, to the formatter to guarantee the weekday and month names render in English regardless of the system’s default locale.
▼ Solution & Explanation
Explanation:
EEEE: Renders the full weekday name, such asFriday, rather than an abbreviation likeFri.MMMM: Renders the full month name, such asJuly, following the same full-versus-abbreviated pattern convention as the weekday.hh:mm a:hhis the 12-hour clock hour,mmis minutes, and the literalainserts the localized AM or PM marker at the end.Locale.ENGLISH: Forces the weekday and month names to render in English, so the output stays consistent even if this code runs on a system configured with a different default locale.
Exercise 21: Parsing a Date String
Problem Statement: Convert a string representing a date (e.g., "2026-12-25") into a LocalDate object using DateTimeFormatter.
Purpose: This exercise introduces parsing, the reverse of formatting, where a plain text string is converted back into a structured LocalDate object that supports date arithmetic and comparisons.
Given Input: dateString = "2026-12-25"
Expected Output: Parsed date: 2026-12-25
▼ Hint
- Build a
DateTimeFormattermatching the exact layout of the input string, such as"yyyy-MM-dd". - Call the static method
LocalDate.parse(text, formatter), passing both the string and the formatter. - The resulting object is a genuine
LocalDate, not just a validated string, so it immediately supports methods likeplusDays()orgetDayOfWeek().
▼ Solution & Explanation
Explanation:
DateTimeFormatter.ofPattern("yyyy-MM-dd"): Describes the exact shape the input text must follow in order to be parsed successfully.LocalDate.parse(dateString, formatter): Reads the string according to that pattern and constructs a realLocalDateobject from it.- Result type: Once parsed,
datebehaves exactly like any otherLocalDate, whether it was built from a string, fromnow(), or fromLocalDate.of(). - Alternative: Since
"2026-12-25"already matches the default ISO-8601 format,LocalDate.parse(dateString)without any formatter would also work here. An explicit formatter becomes necessary once the input string uses a non-standard layout.
Exercise 22: Parsing a Date-Time with an Offset
Problem Statement: Parse a complex date-time string containing a text layout (e.g., "2026-07-03T15:30:00-05:00") into a proper Java object.
Purpose: This exercise introduces OffsetDateTime, used when a date-time string includes a fixed UTC offset, information that a plain LocalDateTime would simply discard.
Given Input: dateTimeString = "2026-07-03T15:30:00-05:00"
Expected Output:
Parsed: 2026-07-03T15:30-05:00 Offset: -05:00
▼ Hint
- Use
OffsetDateTimerather thanLocalDateTime, since the string includes a UTC offset that needs somewhere to live. - Since this string already matches the standard ISO-8601 offset format,
OffsetDateTime.parse(text)works directly without needing a customDateTimeFormatter. - Call
getOffset()on the result to access the parsed offset on its own.
▼ Solution & Explanation
Explanation:
OffsetDateTime.parse(dateTimeString): Parses both the local date-time portion and the trailing-05:00offset in one step, since the string already follows the default ISO-8601 layoutOffsetDateTimeexpects.- Why not
LocalDateTime: Parsing this same string as aLocalDateTimewould fail, sinceLocalDateTimehas no field to hold the offset information at the end of the string. offsetDateTime.getOffset(): Extracts just the-05:00portion as a standaloneZoneOffsetobject, separate from the date and time fields.- Seconds dropped in output: The printed result shows
15:30rather than15:30:00, since the default formatting omits the seconds field whenever it is exactly zero, the same behavior seen withLocalDateTime.
Exercise 23: 24-Hour and 12-Hour Time Formats
Problem Statement: Print the current time in a strict 24-hour format (HH:mm:ss) and a localized 12-hour AM/PM format.
Purpose: This exercise practices formatting the same underlying time in two different, commonly requested layouts by building and applying two separate DateTimeFormatter instances.
Given Input: none (the current time is read directly from the system clock)
Expected Output (actual values depend on the moment you run this):
24-hour format: 15:45:22 12-hour format: 03:45:22 PM
▼ Hint
- Uppercase
HHrepresents the 24-hour clock hour, from 00 to 23. - Lowercase
hhrepresents the 12-hour clock hour, from 01 to 12, and needs a trailingapattern letter to show AM or PM. - Build two separate
DateTimeFormatterinstances, one for each pattern, and apply both to the sameLocalTime.
▼ Solution & Explanation
Explanation:
"HH:mm:ss": Uses the 24-hour hour field, so 3:45 PM prints as15:45:22with no AM/PM marker needed."hh:mm:ss a": Uses the 12-hour hour field paired with theamarker, so the same moment prints as03:45:22 PMinstead.- Same underlying
now, two formatters: Both formatted strings describe the exact same point in time, just laid out according to two different pattern rules. Locale.ENGLISH: Ensures the AM/PM marker renders in English, since some locales use different text or symbols for that marker.
Exercise 24: Handling a Malformed Date String
Problem Statement: Write a program to safely handle and parse a malformed date string by catching the appropriate exception (DateTimeParseException).
Purpose: This exercise introduces DateTimeParseException, the specific unchecked exception thrown when a string does not match the expected pattern or contains an invalid calendar value.
Given Input: badDateString = "2026-13-40" (month 13 and day 40 do not exist)
Expected Output: Error: Invalid date format - Text '2026-13-40' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 13
▼ Hint
- Wrap the
LocalDate.parse()call in atry-catchblock. DateTimeParseExceptionis unchecked, but catching it explicitly still lets you handle bad input gracefully instead of letting the program crash.- Use
e.getMessage()to see exactly which part of the string failed and why.
▼ Solution & Explanation
Explanation:
LocalDate.parse(badDateString): Attempts to interpret"2026-13-40"as an ISO date, but fails as soon as it validates the month field.DateTimeParseException: Thrown specifically for parsing failures, distinct from other exceptions, making it easy to catch parsing problems without accidentally catching unrelated bugs.- Why month fails first: The parser validates each field as it goes, so it reports the invalid month value
13immediately, without ever getting to check whether day40would have been valid too. e.getMessage(): Returns a detailed, specific explanation of exactly what went wrong and where, which is far more useful for debugging than a generic failure message.
Exercise 25: Current Time in a Different Time Zone
Problem Statement: Get the current time in a completely different time zone (e.g., "America/New_York" or "Europe/London") using ZonedDateTime.
Purpose: This exercise introduces ZonedDateTime, which carries full time zone rules, including daylight saving transitions, unlike OffsetDateTime, which only stores a fixed offset.
Given Input: none (the current moment is read directly from the system clock)
Expected Output (actual values depend on the moment you run this):
New York time: 2026-07-03T06:15:22.418732-04:00[America/New_York] London time: 2026-07-03T11:15:22.418732+01:00[Europe/London]
▼ Hint
- Use
ZonedDateTime.now(zoneId), passing aZoneIdbuilt from a region string like"America/New_York". - Each call to
now(zoneId)reads the same underlying instant, just displayed according to that specific zone’s rules. - The printed offset can differ between zones and can even change for the same zone depending on daylight saving time.
▼ Solution & Explanation
Explanation:
ZoneId.of("America/New_York"): Represents a named geographic region with its own complete set of historical and current offset rules, including daylight saving transitions.ZonedDateTime.now(zoneId): Captures the current instant and immediately renders it in local date and time fields for that specific zone.- Bracketed zone name in output: The trailing
[America/New_York]in the printed result distinguishes aZonedDateTimefrom anOffsetDateTime, showing which named zone’s rules were actually applied. - Why the offsets differ: Both lines represent the exact same real-world moment, but
America/New_YorkandEurope/Londonhave different UTC offsets, so their local time-of-day fields naturally differ too.
Exercise 26: Listing Available Zone IDs
Problem Statement: Print a list of all available zone IDs supported by the system using ZoneId.getAvailableZoneIds().
Purpose: This exercise shows how to discover every valid zone name the JVM recognizes, useful when building a dropdown of selectable time zones or validating user input against real zone names.
Given Input: none
Expected Output (the exact count and first entries can vary slightly by JDK version):
Total available zone IDs: 601 Africa/Abidjan Africa/Accra Africa/Addis_Ababa Africa/Algiers Africa/Asmara
▼ Hint
ZoneId.getAvailableZoneIds()returns aSet<String>, so the entries have no guaranteed order on their own.- Use
size()to report the total count directly from the set. - Sort the set with a stream before printing a small sample, so the output is at least consistent and readable across runs.
▼ Solution & Explanation
Explanation:
ZoneId.getAvailableZoneIds(): Returns every zone name the JVM currently recognizes, sourced from its built-in copy of the IANA time zone database.zoneIds.size(): Reports the total number of recognized zone names, which changes slightly between JDK releases as the underlying time zone database is updated..sorted(): Since aSethas no inherent order, sorting the stream alphabetically before printing makes the sample output predictable and easy to read..limit(5): Restricts the printed sample to just the first five entries alphabetically, since printing all several hundred zone names at once would be excessive for a simple demonstration.
Exercise 27: Checking for Friday the 13th
Problem Statement: Write a program to check if a specific date falls on an infamous “Friday the 13th”.
Purpose: This exercise combines two separate checks on the same date, the day-of-month value and the day-of-week value, into a single boolean condition.
Given Input: LocalDate.of(2026, 2, 13)
Expected Output: 2026-02-13 is Friday the 13th: true
▼ Hint
- Use
getDayOfMonth()to check whether the date falls on the 13th. - Use
getDayOfWeek()compared against theDayOfWeek.FRIDAYenum constant to check the weekday. - Combine both checks with
&&, since both conditions must be true at once.
▼ Solution & Explanation
Explanation:
date.getDayOfMonth() == 13: Checks the numeric day-of-month field directly against the literal value 13.date.getDayOfWeek() == DayOfWeek.FRIDAY: Compares the computed weekday enum constant againstFRIDAY, using==since enum constants are singleton instances that can be compared safely this way.&&: Requires both conditions to hold simultaneously, since a date could be the 13th on a different weekday, or a Friday on a different day of the month, without qualifying.LocalDate.of(2026, 2, 13): This particular date does land on a Friday, so both conditions are satisfied and the result istrue.
Exercise 28: Listing All Mondays in a Month
Problem Statement: Given a year and a month, write a program that lists all the Mondays that occur during that specific month.
Purpose: This exercise combines YearMonth with a day-by-day scanning loop, showing how to walk through every date in a given month and filter for a specific weekday.
Given Input: year = 2026, month = 7 (July)
Expected Output:
Mondays in 2026-07: 2026-07-06 2026-07-13 2026-07-20 2026-07-27
▼ Hint
- Use
YearMonth.of(year, month)to represent the target month, and callatDay(1)to get its first date. - Loop day by day using
plusDays(1), stopping oncegetMonthValue()no longer matches the target month. - Inside the loop, check
getDayOfWeek() == DayOfWeek.MONDAYbefore printing each date.
▼ Solution & Explanation
Explanation:
YearMonth.of(year, month): Represents a specific month without needing a particular day, useful as an anchor for month-wide calculations like this one.yearMonth.atDay(1): Produces the first calendar date of that month, used here as the starting point for the scan.while (date.getMonthValue() == month): Keeps the loop going only whiledateis still within the target month, naturally stopping once it rolls over into the next one.date.plusDays(1): Advances the scan one day at a time, checking every single date in the month for a match againstDayOfWeek.MONDAY.
Exercise 29: Month Lengths for a Given Year
Problem Statement: Calculate the length (total days) of every single month for a given year to account for leap years automatically.
Purpose: This exercise loops over the Month enum’s built-in values and uses lengthOfMonth(), which already factors in leap years, rather than hardcoding month lengths manually.
Given Input: year = 2028 (a leap year)
Expected Output:
JANUARY: 31 days FEBRUARY: 29 days MARCH: 31 days APRIL: 30 days MAY: 31 days JUNE: 30 days JULY: 31 days AUGUST: 31 days SEPTEMBER: 30 days OCTOBER: 31 days NOVEMBER: 30 days DECEMBER: 31 days
▼ Hint
- Loop over
Month.values(), which gives every month constant in calendar order. - For each month, build a
LocalDateusing that month and the target year, with the day set to 1. - Call
lengthOfMonth()on that date, which returns how many days the month actually has, correctly adjusting February for leap years.
▼ Solution & Explanation
Explanation:
Month.values(): Returns all twelveMonthenum constants in calendar order, fromJANUARYthroughDECEMBER, ready to loop over directly.LocalDate.of(year, month, 1): Builds a date on the first of each month for the target year. The day value itself does not affect the resulting month length, only the year and month do.lengthOfMonth(): Returns the correct number of days for that specific month and year, automatically returning 29 for February in a leap year and 28 otherwise.- 2028 as a leap year: Since 2028 is divisible by 4 and not by 100, February correctly reports 29 days in the output, confirming the leap year logic is applied automatically.
Exercise 30: Time Difference Between Two Cities
Problem Statement: Find the exact time difference (in hours) between two different cities at the current moment (e.g., the offset difference between Tokyo and Chicago).
Purpose: This closing exercise combines ZonedDateTime with ZoneOffset arithmetic, showing how to compute a live difference between two zones that correctly accounts for daylight saving time on either side.
Given Input: none (both times are read from the system clock, in their respective zones)
Expected Output (actual clock values depend on the moment you run this, though the hour difference stays stable across most of the year):
Tokyo time: 2026-07-04T05:15:22.418732+09:00[Asia/Tokyo] Chicago time: 2026-07-03T15:15:22.418732-05:00[America/Chicago] Difference: 14 hours
▼ Hint
- Get the current
ZonedDateTimefor each city separately, usingZoneId.of("Asia/Tokyo")andZoneId.of("America/Chicago"). - Call
getOffset()on each to retrieve its currentZoneOffset, which reflects any active daylight saving adjustment. - Use
getTotalSeconds()on each offset, subtract them, and divide by 3600 to convert the difference into whole hours.
▼ Solution & Explanation
Explanation:
ZonedDateTime.now(ZoneId.of(...)): Captures the current moment as seen locally in each named zone, including whichever offset is currently active for that location.getOffset(): Retrieves just the current UTC offset for that zone, such as+09:00for Tokyo, which does not observe daylight saving, or-05:00for Chicago during its daylight saving period.tokyoOffset.getTotalSeconds() - chicagoOffset.getTotalSeconds(): Subtracts the two offsets, measured in total seconds, giving the raw difference before converting to a more readable unit.differenceInSeconds / 3600: Converts the raw second difference into whole hours, producing the final, easily understood hour gap between the two cities.

Leave a Reply