Nhận ngày đầu tiên và ngày cuối cùng của tháng bằng cách sử dụng threeten, LocalDate


126

Tôi có LocalDate cần lấy ngày đầu tiên và ngày cuối cùng của tháng. Làm thế nào để làm điều đó?

ví dụ. 13/2/2014 Tôi cần lấy 1/2/201428/2/2014ở định dạng LocalDate .

Sử dụng lớp LocalDate threeten.

Câu trả lời:


179

Chỉ cần sử dụng withDayOfMonthlengthOfMonth():

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.withDayOfMonth(initial.lengthOfMonth());

3
FYI thấy câu trả lời khác
assylias

147

API được thiết kế để hỗ trợ một giải pháp phù hợp chặt chẽ với các yêu cầu kinh doanh

import static java.time.temporal.TemporalAdjusters.*;

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.with(firstDayOfMonth());
LocalDate end = initial.with(lastDayOfMonth());

Tuy nhiên, các giải pháp của Jon cũng ổn.


5
Đi với cái này, hãy sử dụng các tài nguyên API được tạo riêng để xử lý vấn đề cụ thể này.
jpangamarca

87

YearMonth

Để hoàn thiện và trang nhã hơn theo quan điểm của tôi, hãy xem cách sử dụng YearMonthlớp này.

YearMonth month = YearMonth.from(date);
LocalDate start = month.atDay(1);
LocalDate end   = month.atEndOfMonth();

Đối với ngày đầu tiên và ngày cuối cùng của tháng hiện tại, điều này sẽ trở thành:

LocalDate start = YearMonth.now().atDay(1);
LocalDate end   = YearMonth.now().atEndOfMonth();

8
Giải pháp tốt nhất của tất cả.
Agustí Sánchez

Thông tin bổ sung: YearMonth yearMonth = YearMonth.parse ("202004", DateTimeFormatter.ofPattern ("yyyyMM"));
egemen

những ưu điểm của nó so với LocalDate withphương pháp là gì?
AndrewBloom

@AndrewBloom bạn không cần phải sử dụng hàm tĩnh để lấy ngày cuối cùng của tháng và ít nhất trong ví dụ thứ hai, bạn không cần phải có một LocalDatephiên bản để bắt đầu.
herman

18

Câu trả lời của Jon Skeets là đúng và xứng đáng nhận được sự ủng hộ của tôi, chỉ cần thêm giải pháp hơi khác này để hoàn thiện:

import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.with(lastDayOfMonth());

2
Kính gửi downvoter, thành thật mà nói, tôi không hiểu downvote bởi vì câu trả lời của tôi thậm chí là một ngày trước câu trả lời của JodaStephen và chỉ đến phần mới thú vị chủ yếu, cụ thể là bộ điều chỉnh thời gian cho cuối tháng. Đó là tôi chưa "sao chép" câu trả lời từ bất kỳ ai khác.
Meno Hochschild

Câu trả lời chính xác! Giải pháp này tốt hơn vì nó được đề xuất trong tài liệu : "... tìm ngày đầu tiên hoặc ngày cuối cùng của tháng"
peterchaula

4

Nếu ai đó đến tìm kiếm ngày đầu tiên của tháng trướcngày cuối cùng của tháng trước :

public static LocalDate firstDayOfPreviousMonth(LocalDate date) {
        return date.minusMonths(1).withDayOfMonth(1);
    }


public static LocalDate lastDayOfPreviousMonth(LocalDate date) {
        return date.withDayOfMonth(1).minusDays(1);
    }

Mã tốt, nhưng trong Stack Overflow, một Câu trả lời phải giải quyết các chi tiết cụ thể của Câu hỏi.
Basil Bourque

Cảm ơn bạn, tôi đồng ý. Đôi khi chúng tôi tìm thấy mã liên quan trong chuỗi, vì tôi cũng tìm kiếm mã này. Tôi chỉ đặt nó cho những người dùng như vậy. Hy vọng điều đó là ổn. Cảm ơn.
Anil Bhaskar

3
 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);

Vui lòng mô tả câu trả lời của bạn
smilyface

1

Bạn có thể thử điều này để tránh chỉ ra ngày tùy chỉnh và nếu cần hiển thị ngày bắt đầu và ngày kết thúc của tháng hiện tại:

    LocalDate start = LocalDate.now().minusDays(LocalDate.now().getDayOfMonth()-1);
    LocalDate end = LocalDate.now().minusDays(LocalDate.now().getDayOfMonth()).plusMonths(1);
    System.out.println("Start of month: " + start);
    System.out.println("End of month: " + end);

Kết quả:

>     Start of month: 2019-12-01
>     End of month: 2019-12-30

1
Nó có vẻ hơi phức tạp đối với tôi. Nó cũng không cho kết quả chính xác. Ngày cuối cùng của tháng này là 2019-12-31, nhưng đoạn mã của bạn đã in 2019-12-30.
Ole VV

0

Thử cái này:

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);         
LocalDate end = initial.withDayOfMonth(initial.getMonthOfYear().getLastDayOfMonth(false));
System.out.println(start);
System.out.println(end);

bạn có thể tìm thấy đầu ra mong muốn nhưng cần quan tâm đến tham số true / false cho phương thức getLastDayOfMonth

tham số đó biểu thị năm nhuận


Không cần sử dụng getLastDayOfMonth- hãy xem câu trả lời của tôi để biết cách tiếp cận đơn giản hơn.
Jon Skeet

0

nếu bạn chỉ muốn làm điều đó với lớp LocalDate:

LocalDate initial = LocalDate.of(2014, 2, 13);

LocalDate start = LocalDate.of(initial.getYear(), initial.getMonthValue(),1);

// Idea: the last day is the same as the first day of next month minus one day.
LocalDate end = LocalDate.of(initial.getYear(), initial.getMonthValue(), 1).plusMonths(1).minusDays(1);

0

Chỉ ở đây để hiển thị cách triển khai của tôi cho giải pháp @herman

ZoneId americaLaPazZone = ZoneId.of("UTC-04:00");

static Date firstDateOfMonth(Date date) {
  LocalDate localDate = convertToLocalDateWithTimezone(date);
  YearMonth baseMonth = YearMonth.from(localDate);
  LocalDateTime initialDate = baseMonth.atDay(firstDayOfMonth).atStartOfDay();
  return Date.from(initialDate.atZone(americaLaPazZone).toInstant());
}

static Date lastDateOfMonth(Date date) {
  LocalDate localDate = convertToLocalDateWithTimezone(date);
  YearMonth baseMonth = YearMonth.from(localDate);
  LocalDateTime lastDate = baseMonth.atEndOfMonth().atTime(23, 59, 59);
  return Date.from(lastDate.atZone(americaLaPazZone).toInstant());
}

static LocalDate convertToLocalDateWithTimezone(Date date) {
  return LocalDateTime.from(date.toInstant().atZone(americaLaPazZone)).toLocalDate();
}

LocalDateTimechính xác là lớp sai được sử dụng ở đây. Bạn đang loại bỏ thông tin vùng / bù đắp có giá trị.
Basil Bourque

Câu hỏi yêu cầu giá trị chỉ ngày tháng, không phải giá trị ngày tháng với thời gian mà bạn tìm kiếm ở đây. Và lớp kế thừa khủng khiếp Datekhông liên quan gì đến Câu hỏi, và thường nên tránh.
Basil Bourque

1
Đối với múi giờ La Paz, vui lòng sử dụng chính xác hơn ZoneId.of("America/La_Paz"). Đối với các ngày hiện tại, nó sẽ cho kết quả tương tự, nhưng có thể không cho các ngày lịch sử hoặc các ngày trong tương lai xa hơn.
Ole VV
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.