How do I get number of each day for a certain month in Java?

You can get the number of each day (Monday, Tuesday, etc.) for a specific month in Java using the java.time package introduced in Java 8. In the following code snippet we will use a loop to iterate the dates in the month. The number of loop is equals to the number of days in the month.

You can run this code to get the count of each day of the week for any specific month and year. Here’s a sample code to achieve that:

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.EnumMap;
import java.util.Map;

public class DaysOfWeekInMonthWithLoop {

    public static Map<DayOfWeek, Integer> getDaysCountForMonth(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate firstOfMonth = yearMonth.atDay(1);
        LocalDate lastOfMonth = yearMonth.atEndOfMonth();

        Map<DayOfWeek, Integer> daysCount = new EnumMap<>(DayOfWeek.class);

        for (DayOfWeek day : DayOfWeek.values()) {
            daysCount.put(day, 0);
        }

        for (LocalDate date = firstOfMonth; !date.isAfter(lastOfMonth); date = date.plusDays(1)) {
            DayOfWeek dayOfWeek = date.getDayOfWeek();
            daysCount.put(dayOfWeek, daysCount.get(dayOfWeek) + 1);
        }

        return daysCount;
    }

    public static void main(String[] args) {
        int year = 2024;
        int month = 10; // October

        Map<DayOfWeek, Integer> daysCount = getDaysCountForMonth(year, month);

        for (Map.Entry<DayOfWeek, Integer> entry : daysCount.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

Output:

MONDAY: 4
TUESDAY: 5
WEDNESDAY: 5
THURSDAY: 5
FRIDAY: 4
SATURDAY: 4
SUNDAY: 4

What we do in the code snippet above:

  1. YearMonth: Used to represent the year and month. You create an instance of YearMonth for the desired year and month.
  2. LocalDate: Represents a date (year, month, day). firstOfMonth is the first day of the month and lastOfMonth is the last day of the month.
  3. EnumMap: A specialized map for use with enum keys, which in this case are days of the week (from DayOfWeek enum).
  4. Loop through Dates: Iterate from the first to the last day of the month. For each date, get the day of the week and update the count in the map.

Another solution that we can use is to calculate the number of days using a simple mathematical calculations instead of iterating through the dates of the month.

The refined approach:

  1. Determine the first day of the month.
  2. Calculate the base number of times each day appears:
    • Each day will appear at least daysInMonth / 7 times because every 7-day week will have each day once.
    • The remainder from daysInMonth % 7 will determine how many days are left over from complete weeks, starting from the first day of the month.

Here is how we can implement it:

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.EnumMap;
import java.util.Map;

public class DaysOfWeekInMonth {

    public static Map<DayOfWeek, Integer> getDaysCountForMonth(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate firstDayOfMonth = yearMonth.atDay(1);

        int daysInMonth = yearMonth.lengthOfMonth();
        DayOfWeek firstDayOfWeek = firstDayOfMonth.getDayOfWeek();

        Map<DayOfWeek, Integer> daysCount = new EnumMap<>(DayOfWeek.class);

        int baseCount = daysInMonth / 7;
        int extraDays = daysInMonth % 7;

        for (DayOfWeek day : DayOfWeek.values()) {
            daysCount.put(day, baseCount);
        }

        for (int i = 0; i < extraDays; i++) {
            DayOfWeek currentDay = firstDayOfWeek.plus(i);
            daysCount.put(currentDay, daysCount.get(currentDay) + 1);
        }

        return daysCount;
    }

    public static void main(String[] args) {
        int year = 2024;
        int month = 10; // October

        Map<DayOfWeek, Integer> daysCount = getDaysCountForMonth(year, month);

        for (Map.Entry<DayOfWeek, Integer> entry : daysCount.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

Output:

MONDAY: 4
TUESDAY: 5
WEDNESDAY: 5
THURSDAY: 5
FRIDAY: 4
SATURDAY: 4
SUNDAY: 4

In this approach:

  1. YearMonth: Represents the year and month.
  2. LocalDate: Determines the first day of the month.
  3. DayOfWeek: Identifies the day of the week for the first day of the month.
  4. EnumMap: Stores the count of each day of the week.
  5. Base Count and Remainder:
    • baseCount: Calculates how many whole weeks (7 days) fit in the month.
    • extraDays: Calculates the remaining days after accounting for whole weeks.
    • Initialize each count in the map to baseCount.
    • Add 1 to the first extraDays days in the week starting from firstDayOfWeek.

This approach avoids explicitly iterating over each day in the month and relies on mathematical operations to determine the count of each day of the week.

How do I convert date string from one format to another format?

In the following code snippet we will see hot to change a date from one format to another format. For example from 2024-11-04 to 04-Nov-24 format in Java. We can use the DateTimeFormatter class from the java.time.format package to do the conversion.

The steps are:

  • Parse the original date string.
  • Format it to the desired pattern.

Here’s the complete code to do this:

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class DateFormatConversion {
    public static void main(String[] args) {
        // The original date string
        String originalDate = "2024-11-04";

        // Define the input and output date formats
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("dd-MMM-yy");

        // Parse the original date
        LocalDate date = LocalDate.parse(originalDate, inputFormatter);

        // Format the date to the desired pattern
        String formattedDate = date.format(outputFormatter);

        // Print the formatted date
        System.out.println(formattedDate);
    }
}

Output:

04-Nov-24

In the code above we define two formatters, one for the original date format, and the second one is for the new date format. The input formatter matches the original date format (yyyy-MM-dd). The output formatter specifies the desired format (dd-MMM-yy).

We use the LocalDate.parse() method to parse the string of original date into a LocalDate object. Next, we use the LocalDate.format() method to convert into a new date format using the defined formatter object.

This approach uses java.time API introduced in Java 8, which is the recommended way to handle date and time in Java due to its immutability and thread-safety features.

How do I determine if a date falls between two dates?

Java provides different ways to determine if a certain date falls within a specified range. In this article, we’ll look at examples using the old java.util.Date and java.util.Calendar classes, as well as the newer Java Date Time API.

Using java.util.Date and java.util.Calendar

Before Java 8, you’d have to use Date or Calendar to work with dates:

package org.kodejava.datetime;

import java.util.Calendar;

public class CheckDateRange {
    public static void main(String[] args) {
        Calendar start = Calendar.getInstance();
        start.set(2024, Calendar.JANUARY, 1);
        Calendar end = Calendar.getInstance();
        end.set(2024, Calendar.DECEMBER, 31);
        Calendar target = Calendar.getInstance();
        target.set(2024, Calendar.JUNE, 15);

        if ((target.after(start) || target.equals(start)) &&
            (target.before(end) || target.equals(end))) {
            System.out.println("The date is within the range.");
        } else {
            System.out.println("The date is not within the range.");
        }
    }
}

The disadvantage with this approach is the excessive verbosity and error-prone copy-pasting necessary for setting up the Calendar instances.

The Java 8 Way – Using java.time.LocalDate

Java 8 introduced the new Java Date Time API, which replaced the inconsistent Date and Calendar classes with the more intuitive LocalDate, LocalTime, LocalDateTime, and ZonedDateTime. Here’s the same task performed using LocalDate:

package org.kodejava.datetime;

import java.time.LocalDate;

public class AnotherCheckDateRange {
    public static void main(String[] args) {
        LocalDate startDate = LocalDate.of(2024, 1, 1);
        LocalDate endDate = LocalDate.of(2024, 12, 31);
        LocalDate targetDate = LocalDate.of(2024, 6, 15);

        if ((!targetDate.isBefore(startDate)) && (!targetDate.isAfter(endDate))) {
            System.out.println("The date is within the range.");
        } else {
            System.out.println("The date is not within the range.");
        }
    }
}

In this code, startDate and endDate define the range of dates. The targetDate is the date you want to check.

The isBefore() method returns true if the targetDate is before the startDate, and the isAfter() method returns true if the targetDate is after the endDate. So, if targetDate is not before the startDate and not after the endDate, it means that the targetDate is between startDate and endDate (inclusive). If the targetDate is exactly the same as startDate or endDate, this condition will also return true.

This simplified API requires significantly less code and eliminates a number of potential bugs and inconsistencies.

Conclusion

The older java.util.Date and java.util.Calendar facilities for working with dates are widely considered difficult to use and error-prone. While they work for simple tasks, the newer Java Date Time API is recommended for all new applications due to its simplicity, consistency, and flexibility. It aligns with ISO standards and covers a comprehensive range of use-cases needed for date-time calculations. Migrating from older APIs to Java 8 Date Time API is likely advantageous for most projects.

How do I convert LocalDate to ZonedDateTime?

You can use the atStartOfDay() method from LocalDate class to convert a LocalDate into a LocalDateTime. Then, you need to convert LocalDateTime to a ZonedDateTime using the atZone() method.

Here is an example:

package org.kodejava.datetime;

import java.time.*;

public class LocalDateToZonedDateTimeExample {
    public static void main(String[] args) {
        // Create a LocalDate
        LocalDate date = LocalDate.of(2023, Month.JULY, 9);
        System.out.println("LocalDate: " + date);

        // Convert LocalDate to LocalDateTime
        LocalDateTime dateTime = date.atStartOfDay();
        System.out.println("LocalDateTime: " + dateTime);

        // Convert LocalDateTime to ZonedDateTime
        ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.systemDefault());
        System.out.println("ZonedDateTime: " + zonedDateTime);
    }
}

Output:

LocalDate: 2023-07-09
LocalDateTime: 2023-07-09T00:00
ZonedDateTime: 2023-07-09T00:00+08:00[Asia/Makassar]

In this example, we’re creating a LocalDate for July 9, 2023. Then we’re converting it to a LocalDateTime, and then to a ZonedDateTime. The atStartOfDay() method returns a LocalDateTime set to the start of the day (00:00) on the date of this LocalDate. The atZone() method then takes the ZoneId and returns a ZonedDateTime representing the start of the day in that timezone.

The ZoneId.systemDefault() returns the system default time zone. If you want to convert it to a specific time zone, you can specify the timezone as a string, like this: ZoneId.of("America/New_York").

How do I use java.time.Instant class of Java Date-Time API?

The java.time.Instant class in the Java Date-Time API is an immutable representation of a point in time. It stores a long count of seconds from the epoch of the first moment of 1970 UTC, plus a number of nanoseconds for the further precision within that second.

The java.time.LocalDate class represents a date without a time or time zone. It is used to represent just a date as year-month-day (e.g., 2023-03-27) in the ISO-8601 calendar system.

The java.time.LocalTime class represents a time without a date or time zone. It is used to represent just a time as hour-minute-second (e.g., 13:45:20).

It’s also worth noting that Instant class is part of Java 8’s new date and time API which was brought in to address the shortcomings of the old java.util.Date and java.util.Calendar API.

Here’s a quick example of how to use the Instant class:

package org.kodejava.datetime;

import java.time.Instant;

public class InstantExample {
    public static void main(String[] args) {
        // Get the current point in time
        Instant now = Instant.now();
        System.out.println("Current time: " + now);

        // Add duration of 500 seconds from now
        Instant later = now.plusSeconds(500);
        System.out.println("500 seconds later: " + later);

        // Subtract duration of 500 seconds from now
        Instant earlier = now.minusSeconds(500);
        System.out.println("500 seconds earlier: " + earlier);

        // Compare two Instants
        int comparison = now.compareTo(later);
        if (comparison < 0) {
            System.out.println("Now is earlier than later");
        } else if (comparison > 0) {
            System.out.println("Now is later than later");
        } else {
            System.out.println("Now and later are at the same time");
        }
    }
}

Output:

Current time: 2024-01-18T09:26:56.152268Z
500 seconds later: 2024-01-18T09:35:16.152268Z
500 seconds earlier: 2024-01-18T09:18:36.152268Z
Now is earlier than later

In this example, Instant.now() is used to get the current Instant. Various methods like plusSeconds(), minusSeconds(), and compareTo() are used to manipulate and compare the Instant.

LocalDate and LocalTime are local in the sense that they represent date and time from the context of the observer, without a time zone.

To connect Instant with LocalDate and LocalTime, you need a time zone. This is because Instant is in UTC and LocalDate/LocalTime are in a local time zone, so you need to explicitly provide a conversion between them.

Here’s how you convert an Instant to a LocalDate and a LocalTime:

package org.kodejava.datetime;

import java.time.*;

public class InstantConvertExample {
    public static void main(String[] args) {
        Instant now = Instant.now();
        System.out.println("Instant: " + now);

        // Get the system default timezone
        ZoneId zoneId = ZoneId.systemDefault(); 

        LocalDate localDate = now.atZone(zoneId).toLocalDate();
        System.out.println("LocalDate: " + localDate);

        LocalTime localTime = now.atZone(zoneId).toLocalTime();
        System.out.println("LocalTime: " + localTime);
    }
}

Here Instant.now() gives the current timestamp. .atZone(ZoneId.systemDefault()) converts it to ZonedDateTime which is then converted to LocalDate and LocalTime by using .toLocalDate() and .toLocalTime() respectively.

You can also go from LocalDate and LocalTime back to Instant. Here’s how:

package org.kodejava.datetime;

import java.time.*;

public class ToInstantExample {
    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instantFromDateAndTime = LocalDateTime.of(localDate, localTime).atZone(zoneId).toInstant();

        System.out.println("Instant from LocalDate and LocalTime: " + instantFromDateAndTime);
    }
}

How do I use TemporalAdjusters dayOfWeekInMonth() method?

dayOfWeekInMonth() is a handy method in java.time.temporal.TemporalAdjusters class that returns an adjuster which changes the date to the n-th day of week in the current month.

Here is an example of how you could use it:

package org.kodejava.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class DayOfWeekInMonthExample {
    public static void main(String[] args) {
        // Current date
        LocalDate date = LocalDate.now();

        // The 2nd Tuesday in the month of the date.
        LocalDate secondTuesday = date.with(
                TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY));

        System.out.println("Current Date: " + date);
        System.out.println("Second Tuesday: " + secondTuesday);
    }
}

Output:

Current Date: 2024-01-18
Second Tuesday: 2024-01-09

This code would display the date of the second Tuesday in the current month.

Here’s what’s going on in this case:

  • TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY) specifies that we want the second occurrence of DayOfWeek.TUESDAY in the current month.

  • date.with(TemporalAdjuster) modifies the LocalDate date based on the TemporalAdjuster that is passed in. The original date object is unchanged; a new LocalDate reflecting the adjusted date is returned.

This TemporalAdjusters method is very useful when you have conditional logic based on things like “if it’s the third Monday of the month, then…”

How do I use java.time.Period class?

java.time.Period is a class that represents a quantity or amount of time in terms of years, months, and days. Here’s a brief guide on how to use it:

1. Creating a Period instance

The Period class provides several static methods named of() and between() to create an instance. To create Period of 1 year, 2 months, and 3 days:

Period period = Period.of(1, 2, 3);

Or you can create a Period using LocalDate:

LocalDate start = LocalDate.of(2020, Month.JANUARY, 1);
LocalDate end = LocalDate.of(2023, Month.MARCH, 31);
Period period = Period.between(start, end);

2. Retrieving Years, Months, and Days

Use the getDays(), getMonths(), and getYears() methods to get the number of days, months, and years in the Period.

int days = period.getDays();
int months = period.getMonths();
int years = period.getYears();

3. Adding/subtracting Period to/from a LocalDate

The LocalDate.plus() or LocalDate.minus() methods can be used to add or subtract a Period from a LocalDate.

LocalDate ld = LocalDate.of(2021, Month.JULY, 1);
Period period = Period.of(1, 2, 3);
LocalDate newDate = ld.plus(period);

In this case, newDate will be 1 year, 2 months, and 3 days after July 1, 2021.

4. Mixing units of time

You can use plusDays(), plusMonths(), or plusYears() to add to a Period.

Period period = Period.of(1, 2, 3);
Period newPeriod = period.plusDays(10);

The newPeriod will then be 1 year, 2 months, and 13 days.

How do I use plus and minus method in the Java Date-Time API?

In the Java Date-Time API, the plus and minus methods can be used to calculate and modify dates, times, date/times, and durations.

Each temporal class (LocalDate, LocalTime, LocalDateTime, and Duration) includes these methods.

Here’s a basic example using the LocalDate class:

package org.kodejava.datetime;

import java.time.LocalDate;

public class PlusMinusExample {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();

        // Calculate the date 5 days into the future
        LocalDate futureDate = date.plusDays(5);
        System.out.println("Date five days in the future: " + futureDate);

        // Calculate the date 5 days in the past.
        LocalDate pastDate = date.minusDays(5);
        System.out.println("Date five days in the past: " + pastDate);
    }
}

Output:

Date five days in the future: 2024-01-22
Date five days in the past: 2024-01-12

You can also use plusWeeks, plusMonths, plusYears, minusWeeks, minusMonths, minusYears methods in a similar manner to add or subtract the respective time period.

Note: All the datetime manipulation methods return a new instance of the date/time object; they do not modify the original object because the classes are immutable.

The plus() and minus() methods in the Java Date-Time API offer finer control over date-time arithmetic by allowing you to add or subtract different types of date-time units such as days, months, or years.

The plus() method is used to add specific time units to a date or time, while the minus() method is used to subtract specific time units.

Here’s an example:

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.Period;

public class PlusMinusOtherExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();

        // 1 year, 2 months, and 3 days.
        Period periodToAdd = Period.of(1, 2, 3);
        LocalDate futureDate = today.plus(periodToAdd);
        System.out.println("Date after adding a period: " + futureDate);

        // 2 years, 4 months, and 6 days.
        Period periodToSubtract = Period.of(2, 4, 6);
        LocalDate pastDate = today.minus(periodToSubtract);
        System.out.println("Date after subtracting a period: " + pastDate);
    }
}

The Period class is part of the Java Date-Time API and is used to represent a quantity of time in terms of years, months, and days.

Remember, you can create a Period using the Period.of(int years, int months, int days) method, where years, months, and days are the specific units of time to be represented.

Here are examples using LocalTime and LocalDateTime:

package org.kodejava.datetime;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class PlusMinusTime {
    public static void main(String[] args) {
        // Creating a LocalTime object and adding/subtracting hours, minutes, seconds
        LocalTime time = LocalTime.now();

        LocalTime futureTime = time.plus(2, ChronoUnit.HOURS);
        System.out.println("Time after two hours: " + futureTime);

        LocalTime pastTime = time.minus(30, ChronoUnit.MINUTES);
        System.out.println("Time 30 minutes ago: " + pastTime);

        // Creating a LocalDateTime object and adding/subtracting days, months, years
        LocalDateTime dateTime = LocalDateTime.now();

        LocalDateTime futureDateTime = dateTime.plus(1, ChronoUnit.YEARS);
        System.out.println("Date and Time one year into the future: " + futureDateTime);

        LocalDateTime pastDateTime = dateTime.minus(2, ChronoUnit.MONTHS);
        System.out.println("Date and Time two months ago: " + pastDateTime);

        // You can also use plus or minus Days, Weeks, Months, Years directly
        LocalDateTime exactDateTimeFuture = dateTime.plusDays(1).plusWeeks(1).plusMonths(1).plusYears(1);
        System.out.println("Date and Time after one day, week, month, and year: " + exactDateTimeFuture);
    }
}

Note that when we are adding/subtracting units like hours, minutes, and seconds, we use java.time.temporal.ChronoUnit. When adding/subtracting days, weeks, months, and years, we use directly plusDays or minusDays and so on.

How do I use atDate() method of Java Date-Time API?

The atDate() method is a part of LocalTime class in the Java Date-Time API. This method combines this time with a date to create an instance of LocalDateTime.

Here’s an example:

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class AtDateExample {
    public static void main(String[] args) {
        // Create a LocalTime instance
        LocalTime time = LocalTime.of(14, 20);

        // Create a LocalDate instance
        LocalDate date = LocalDate.of(2023, 1, 23);

        // Using atDate to combine time and date into a LocalDateTime
        LocalDateTime dateTime = time.atDate(date);

        System.out.println(dateTime);
    }
}

Output:

2023-01-23T14:20

In this example, a LocalTime and a LocalDate are combined into a LocalDateTime using the atDate() method. This method is useful when you have a LocalTime instance and want to combine it with a date. It’s in some sense a converse operation to LocalDate‘s atTime().

How do I use atTime() method of Java Date-Time API?

The atTime() method belongs to the LocalDate class in the Java Date-Time API, not the Date class. This method combines this date with a time to create a LocalDateTime.

Here’s an example:

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class AtTimeExample {
    public static void main(String[] args) {
        // Create a LocalDate instance
        LocalDate date = LocalDate.of(2023, 1, 23);

        // Create a LocalTime instance
        // 24-hour clocks
        LocalTime time = LocalTime.of(13, 45);

        // Use atTime() to combine date and time into a LocalDateTime
        LocalDateTime dateTime = date.atTime(time);

        System.out.println(dateTime);
    }
}

Output:

2023-01-23T13:45

In this example, a LocalDate and a LocalTime are combined into a LocalDateTime using the atTime() method.

The LocalDate class also has an overloaded atTime method that takes the hour and minute directly, instead of a LocalTime instance.

Here’s an example where we set 14 hours and 30 minutes directly.

package org.kodejava.datetime;

import java.time.LocalDate;
import java.time.LocalDateTime;

public class AtTimeOtherExample {
    public static void main(String[] args) {
        // Create a LocalDate instance
        LocalDate date = LocalDate.of(2023, 1, 23);

        // Use atTime() to combine date and hour and minute into a
        // LocalDateTime
        LocalDateTime dateTime = date.atTime(14, 30);

        System.out.println(dateTime);
    }
}

Output:

2023-01-23T14:30

In this example, 14:30 (in 24-hour clock) is directly passed into atTime. There is another version of atTime() that takes hrs, min, and sec. That would look like this:

// include seconds
LocalDateTime dateTime = date.atTime(14, 30, 20);
// include nano seconds
LocalDateTime dateTime = date.atTime(14, 30, 20, 200); 

These are all the overloaded versions of atTime() in LocalDate.

Remember, LocalDate, LocalTime, LocalDateTime and others from Java Date-Time API are designed to replace the old Date and Calendar classes from java.util package. They are more consistent, easier to understand and use.