Thông tin về thời gian ngắt ngày trong Java


121

Tôi có một đối tượng Ngày Java chứa thông tin ngày và giờ. Tôi muốn viết một phương pháp cắt bỏ thông tin thời gian, cắt bớt giờ-phút-giây, vì vậy tôi chỉ còn lại ngày.

Ví dụ đầu vào:

2008-01-01 13:15:00

Sản lượng mong đợi:

2008-01-01 00:00:00

Bạn có một mẹo? Tôi đã thử làm điều gì đó như thế này:

(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)

nhưng tôi đã gặp vấn đề với múi giờ.

Câu trả lời:


178

Cách được khuyến nghị để thực hiện thao tác ngày / giờ là sử dụng một Calendarđối tượng:

Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(dateObject);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long time = cal.getTimeInMillis();

2
@cletus, Có thể xóa thời gian khỏi đối tượng Date không. Tôi muốn ngày thuần túy như 2008-01-01 không có phần thời gian.
Prem

2
Tôi sẽ không nói rằng java.util.Calendar được khuyến khích. Sun / Oracle đã thay thế lớp đó trong Java 8 bằng gói java.time mới. Sử dụng cái đó hoặc Joda-Time.
Basil Bourque

3
Lịch không còn được khuyến khích. Xem stackoverflow.com/a/28868089/40064 nếu bạn đang sử dụng Java 8.
Wim Deblauwe

2
FYI, các lớp date-time cũ rắc rối như java.util.Calendarbây giờ là kế thừa , được thay thế bởi các lớp java.time . Xem Hướng dẫn của Oracle .
Basil Bourque

148

Bạn đã xem phương thức cắt ngắn DateUtils trong Apache Commons Lang chưa?

Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE);

sẽ loại bỏ yếu tố thời gian.


9
Liên kết được cập nhật một lần nữa (come on Apache Quit Movin tài liệu của bạn xung quanh!)
Ogre Psalm33

6
Điểm trừ của phương pháp này là múi giờ trong hoạt động cắt ngắn được thực hiện luôn là múi giờ cục bộ của PC. Vì vậy, nếu bạn làm việc với lịch và ngày trong múi giờ UTC hoặc ở bất kỳ múi giờ nào khác múi giờ địa phương - thì nó có thể cắt bớt ngày không như dự định.
Đám mây

như @Cloud chỉ ra, thực tế là tôi không thấy các ví dụ Lịch ở đây (không kiểm soát được nó) làm cho tôi có chút lo lắng :)
Jaroslav Záruba

Phương pháp đó dài đáng ngạc nhiên và có ít nhất hai bản sửa lỗi.
Pino

42

Bạn đã nhìn vào Joda chưa? Đó là một nhiều cách dễ dàng hơn và trực quan hơn để làm việc với ngày tháng và thời gian. Ví dụ bạn có thể chuyển đổi giữa trivially (nói) LocalDateTimeLOCALDATE đối tượng.

ví dụ: (để minh họa API)

LocalDate date = new LocalDateTime(milliseconds).toLocalDate()

Ngoài ra, nó giải quyết một số vấn đề về an toàn luồng với các bộ định dạng ngày / giờ và được khuyến khích sử dụng để làm việc với bất kỳ sự cố ngày / giờ nào trong Java.


12
Tôi tin rằng nó có. Đó là một đề nghị sử dụng một thư viện tốt hơn chứ không phải chiến đấu với các lớp java.util bị phá vỡ (bằng chứng là câu hỏi)
Brian Agnew

10
Tất nhiên nó liên quan, Joda là thư viện cho thao tác ngày, giờ và lịch trong Java. Sẽ là vô nghĩa nếu không giới thiệu nó.
Joel

1
Vấn đề an toàn luồng rất thú vị, tôi thấy bài đăng này nghiên cứu lỗi Oracle / Hibernate "IllegalArgumentException, sun.util.calendar.ZoneInfo.getOffset (ZoneInfo), oracle.jdbc.driver.DateCommonBinder.zoneOffset (OraclePreparedStatement)". Bài này nói về một vấn đề khác của Oracle chỉ xuất hiện khi tải nặng forum.oracle.com/forums/thread.jspa?threadID=325576 Thực sự rất khó để tạo một đối tượng có mili giây không hợp lệ trong mã bình thường. Đối với tôi, tôi nghĩ rằng tôi sẽ downcast trong chuỗi của mình bằng cách sử dụng Joda, thay vì để Oracle sử dụng những thứ không phải joda có thể nghi ngờ.
Mark Bennett

4
Tôi ước tôi có thể phản đối tất cả những người đã bỏ phiếu cho điều này. Tất cả những người +1 câu trả lời thậm chí không cố gắng trả lời câu hỏi này là ai? Một câu trả lời bằng cách sử dụng Joda sẽ được chào đón nhiều hơn, nhưng đây không phải là nó ...
Ryan

1
@Ryan Làm thế nào câu trả lời này không liên quan? Câu hỏi yêu cầu ngày mà không có thời gian trong ngày. Câu trả lời này trình bày một lớp có mục đích duy nhất là đại diện cho một ngày không có thời gian trong ngày.
Basil Bourque

35

Chỉ là một bản cập nhật nhanh về các lớp java.time hiện được tích hợp trong Java 8 trở lên.

LocalDateTimecó một truncatedTophương pháp giải quyết hiệu quả những gì bạn đang nói ở đây:

LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES)

Điều này sẽ thể hiện thời gian hiện tại chỉ xuống đến phút:

2015-03-05T11:47

Bạn có thể sử dụng một ChronoUnit(hoặc a TemporalUnit) nhỏ hơn DAYS để thực hiện việc cắt bớt (vì việc cắt ngắn chỉ được áp dụng cho phần thời gian của LocalDateTime, không áp dụng cho phần ngày).


3
Bạn chỉ có thể sử dụng ChronoUnits tối đa DAYS - các đơn vị cao hơn sẽ có ngoại lệ.
assylias

26
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();

22

Với Joda bạn có thể dễ dàng có được ngày như mong đợi.

Kể từ phiên bản 2.7 (có thể kể từ một số phiên bản trước đó lớn hơn 2.2), như một người bình luận lưu ý, toDateMidnightđã không được ủng hộ hoặc được đặt tên phù hợp withTimeAtStartOfDay(), làm cho thuận tiện

DateTime.now().withTimeAtStartOfDay()

khả thi.

Thêm lợi ích của một API đẹp hơn.

Với các phiên bản cũ hơn, bạn có thể làm

new DateTime(new Date()).toDateMidnight().toDate()

6
Các phương thức và lớp liên quan đến nửa đêm trong Joda-Time hiện không được dùng nữa. Các nhà phát triển khuyên bạn không nên sử dụng chúng. Thay vào đó hãy sử dụng phương pháp withTimeAtStartOfDay.
Basil Bourque

Cảm ơn bạn đã chỉ ra. Đã cập nhật câu trả lời để xem xét điều này.
h7r

Bạn cũng có thể sử dụng toLocalDateđể lấy một đối tượng thậm chí không có thành phần thời gian.
Charles Wood

FYI, dự án Joda-Time hiện đang ở chế độ bảo trì , với nhóm tư vấn di chuyển sang các lớp java.time . Xem Hướng dẫn của Oracle .
Basil Bourque

8

Tôi đã cắt ngắn với API java8 mới. Tôi đã phải đối mặt với một điều kỳ lạ nhưng nói chung là ...

Instant instant = date.toInstant();
instant = instant.truncatedTo(ChronoUnit.DAYS);
date = Date.from(instant);

từ khóa: java.time, Java 8, LocalDateTime.truncatedTo ()
Alexander Taylor

1
Câu trả lời này chỉ tạo ngày cho ngữ cảnh của múi giờ UTC.
Basil Bourque

6

Sử dụng DateUtils từ Apache, với phần cắt ngắn, như thế này:

DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);

Điều này sẽ cắt ngắn trong TimeZone cục bộ, không phải trong UTC mà Ngày (getTime) đại diện.
epox

6

Đối với dấu thời gian:

timestamp -= timestamp % (24 * 60 * 60 * 1000)

3
Có một lỗi nhỏ trong mã này - dấu ngoặc bên trái không được đặt chính xác, nó phải là dấu thời gian - = timestamp% (24 * 60 * 60 * 1000). Điều này sẽ cắt bớt phần thời gian. Và tôi chắc chắn rằng cách này là đủ hơn so với việc tạo đối tượng Caledar và chơi với các phương thức của nó hoặc thậm chí sử dụng bất kỳ thư viện bên thứ 3 nào khác
Stan

2
Không, đây KHÔNG phải là giải pháp chính xác, HÃY CẨN THẬN. Điều này cũng giống như việc làm tròn giá trị ngày thành giá trị sàn, tức là - bạn có thể nhận được ngày 28 tháng 3 cho dấu thời gian của ngày 29 tháng 3 (theo ngôn ngữ của bạn). Vì vậy, các giải pháp dựa trên Lịch (DateUtils của Apache cũng sử dụng Lịch) là cách duy nhất
Drew

Điều này cũng sẽ không hoạt động khi thời gian thay đổi do thời gian tiết kiệm ánh sáng ban ngày.
Alexandru Severin

5

Từ java.util.Date JavaDocs:

Lớp Ngày đại diện cho một thời điểm cụ thể trong thời gian, với độ chính xác mili giây

và từ java.sql.Date JavaDocs:

Để phù hợp với định nghĩa của SQL DATE, các giá trị mili giây được bao bọc bởi phiên bản java.sql.Date phải được 'chuẩn hóa' bằng cách đặt giờ, phút, giây và mili giây thành 0 trong múi giờ cụ thể mà phiên bản được liên kết .

Vì vậy, cách tốt nhất là sử dụng java.sql.Date nếu bạn không cần phần thời gian

java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());

và đầu ra là:

java.util.Date : Thu Apr 26 16:22:53 PST 2012
java.sql.Date  : 2012-04-26

4

tl; dr

LocalDateTime.parse(                            // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time.
    "2008-01-01 13:15:00".replace( " " , "T" )  // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate()                                  // Extract a date-only value.
.atStartOfDay(                                  // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
    ZoneId.of( "Europe/Paris" )                 // Determining a specific start-of-day requires a time zone.
)                                               // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
.toString()                                     // Generate a String in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets.

2008-01-01T00: 00 + 01: 00 [Châu Âu / Paris]

Để tạo một Chuỗi ở định dạng mong muốn của bạn, hãy chuyển một DateTimeFormatter.

LocalDateTime.parse(                            // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time.
    "2008-01-01 13:15:00".replace( " " , "T" )  // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate()                                  // Extract a date-only value.
.atStartOfDay(                                  // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
    ZoneId.of( "Europe/Paris" )                 // Determining a specific start-of-day requires a time zone.
)                                               // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline.
.format(                                        // Generate a String representing the object’s value.
    DateTimeFormatter.ISO_LOCAL_DATE_TIME       // Built-in predefined formatter close to what you want. 
)
.replace( "T" , " " )                           // Replace the standard’s use of a 'T' in the middle with your desired SPACE character.

2008-01-01 00:00:00

Chi tiết

Các câu trả lời khác đúng, nhưng sử dụng các lớp ngày-giờ cũ hiện đã bị khuôn khổ java.time sửa chữa.

java.time

Khuôn khổ java.time được tích hợp trong Java 8 trở lên. Phần lớn chức năng của java.time được chuyển ngược sang Java 6 & 7 ( ThreeTen-Backport ) và được điều chỉnh thêm cho Android ( ThreeTenABP ).

Trước tiên, hãy thay đổi chuỗi đầu vào để tuân thủ phiên bản chuẩn của định dạng ISO 8601. Các định dạng tiêu chuẩn ISO 8601 được sử dụng theo mặc định trong các lớp java.time để phân tích cú pháp / tạo chuỗi đại diện cho các giá trị ngày-giờ. Chúng ta cần thay thế SPACE đó ở giữa bằng a T.

String input = "2008-01-01 13:15:00".replace( " " , "T" );  // → 2008-01-01T13:15:00

Bây giờ chúng ta có thể phân tích cú pháp nó thành a LocalDateTime, trong đó "Local" có nghĩa là không có địa phương cụ thể. Đầu vào thiếu bất kỳ thông tin lệch-từ-UTC hoặc múi giờ nào.

LocalDateTime ldt = LocalDateTime.parse( input );

ldt.toString ()… 2008-01-01T13: 15: 00

Nếu bạn không quan tâm đến thời gian trong ngày hoặc múi giờ, thì hãy chuyển đổi thành a LocalDate.

LocalDate ld = ldt.toLocalDate();

ld.toString ()… 2008-01-01

Khoảnh khắc đầu tiên trong ngày

Thay vào đó, nếu bạn muốn đặt thời gian trong ngày thành thời điểm đầu tiên trong ngày, hãy sử dụng một ZonedDateTimelớp, sau đó chuyển đổi thành một LocalDateđối tượng để gọi atStartOfDayphương thức của nó . Hãy lưu ý rằng khoảnh khắc đầu tiên có thể không phải là thời điểm 00:00:00do Giờ tiết kiệm ánh sáng ban ngày hoặc có thể là do những bất thường khác.

Múi giờ rất quan trọng bởi vì trong bất kỳ thời điểm nào, ngày khác nhau trên thế giới theo múi. Ví dụ, một vài khoảnh khắc sau nửa đêm ở Paris là một ngày mới đối với người Paris nhưng vẫn là “ngày hôm qua” ở Montréal đối với người Canada.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
LocalDate ldFromZdt = zdt.toLocalDate();
ZonedDateTime zdtStartOfDay = ldFromZdt.atStartOfDay( zoneId );

zdtStartOfDay.toString ()… 2008-01-01T00: 00: 00-05: 00 [Mỹ / Montreal]

UTC

Để xem khoảnh khắc đó qua thấu kính của múi giờ UTC , hãy trích xuất một Instantđối tượng. Cả hai ZonedDateTimeInstantsẽ đại diện cho cùng một thời điểm trên dòng thời gian nhưng xuất hiện dưới dạng hai thời điểm đồng hồ treo tường khác nhau .

An Instantlà lớp khối xây dựng cơ bản trong java.time, luôn ở UTC theo định nghĩa. Sử dụng lớp này thường xuyên, vì bạn thường phải thực hiện logic nghiệp vụ, lưu trữ dữ liệu và trao đổi dữ liệu trong UTC.

Instant instant = zdtStartOfDay.toInstant();

Instant.toString ()… 2008-01-01T05: 00: 00Z

Chúng tôi thấy 5 giờ sáng chứ không phải nửa đêm. Ở định dạng tiêu chuẩn, Zở cuối là viết tắt của Zuluvà có nghĩa là "UTC".


Giới thiệu về java.time

Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian như java.util.Date, Calendar, & SimpleDateFormat.

Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.

Để tìm hiểu thêm, hãy xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow để có nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .

Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của mình. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*lớp.

Lấy các lớp java.time ở đâu?

  • Java SE 8 , Java SE 9 và mới hơn
    • Được xây dựng trong.
    • Một phần của API Java tiêu chuẩn với một triển khai đóng gói.
    • Java 9 bổ sung một số tính năng nhỏ và các bản sửa lỗi.
  • Java SE 6 Java SE 7
    • Phần lớn chức năng của java.time được chuyển ngược sang Java 6 & 7 trong ThreeTen-Backport .
  • Android
    • Các phiên bản triển khai gói Android mới hơn của các lớp java.time.
    • Đối với Android trước đó (<26), các ThreeTenABP dự án thích nghi ThreeTen-backport (nêu trên). Xem Cách sử dụng ThreeTenABP… .

Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là cơ sở chứng minh cho những bổ sung có thể có trong tương lai cho java.time. Bạn có thể tìm thấy một số các lớp học hữu ích ở đây chẳng hạn như Interval, YearWeek, YearQuarter, và nhiều hơn nữa .


2

Sử dụng phương thức của lớp Lịchset() để đặt các trường HOUR_OF_DAY, MINUTE, SECONDMILLISECONDbằng 0.


2

Câu hỏi thật mâu thuẫn. Nó yêu cầu một ngày mà không có thời gian trong ngày nhưng hiển thị một ví dụ với thời gian là 00:00:00.

Joda-Time

UPDATE: Các Joda thời gian dự án hiện đang trong chế độ bảo trì , với đội ngũ tư vấn chuyển đổi sang các java.time lớp. Xem Câu trả lời khác của tôi cho giải pháp java.time.

Thay vào đó, nếu bạn muốn thời gian trong ngày được đặt thành thời điểm đầu tiên trong ngày, hãy sử dụng một DateTimeđối tượng trên thư viện Joda-Time và gọi withTimeAtStartOfDayphương thức của nó . Hãy lưu ý rằng khoảnh khắc đầu tiên có thể không phải là thời điểm 00:00:00do Giờ tiết kiệm ánh sáng ban ngày hoặc có thể là do những bất thường khác.


Đây là câu trả lời dứt khoát (giả định rằng người ta có thể và muốn sử dụng Joda Thời gian)
Clint Eastwood

2

Chỉ là clear()các trường thừa.

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.clear(Calendar.MINUTE);
calendar.clear(Calendar.SECOND);
calendar.clear(Calendar.MILLISECOND);
Date truncatedDate = calendar.getTime();

Từ Java 8, một lựa chọn tốt hơn là sử dụng truncatedTophương thức LocalDateTime, ví dụ:

LocalDateTime.now().truncatedTo(ChronoUnit.DAYS)

Điều này không hiệu quả, vì calendar.clear(Calendar.HOUR_OF_DAY);không rõ giờ. Giải pháp từ @cletus hoạt động OK.
Arcao

Xin lỗi, bạn nói đúng, tôi đã sửa nó, trong nhiều giờ bạn nên đặt giá trị. Nói chung nó gần như cùng một cách làm thế nào để cắt ngắn ngày ...
m190

1

Tôi thực sự khó chịu khi hàm tạo lịch "cải tiến" mới không lấy giá trị int cho mili giây như Date cũ "khủng khiếp". Sau đó tôi đã thực sự vượt qua và viết điều này:

long stuffYou = startTime.getTimeInMillis() % 1000;
startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);

Tôi đã không sử dụng từ "công cụ" vào thời điểm đó, nhưng sau đó tôi phát hiện ra niềm hạnh phúc của điều này:

startTime.set(Calendar.MILLISECOND, 0);

Nhưng tôi vẫn khá lo lắng về nó.


1

Tôi đã khắc phục sự cố như thế này (ở khu 8 phía Đông (giờ Bắc Kinh)):

private Date getTruncatedDate(Date d) {
    if (d == null) {
        return null;
    }
    long h = 60 * 60 * 1000L;
    long dateStamp = d.getTime() - (d.getTime() + 8 * h) % (24 * h);
    return new Date(dateStamp);
}

Trước hết, bạn nên rõ ràng tem thời gian là gì. Dấu thời gian là tổng số mili giây kể từ ngày 01 tháng 1 00:00:00 năm 1970 theo giờ GMT (giống như UTC) hoặc 08:00:00 CST ngày 01 tháng 1 năm 1970 đến nay.

Hãy nhớ: Dấu thời gian không phụ thuộc vào múi giờ.

Vì vậy, bạn sẽ nhận được cùng một kết quả với câu lệnh sau ở các múi giờ khác nhau:

System.out.println(new Date().getTime());

System.out.println(new Date(0));

in thông tin thời gian khác nhau ở các múi giờ khác nhau: Nếu bạn đặt múi giờ máy tính của mình là UTC, bạn sẽ nhận được

Thu Jan 01 00:00:00 UTC 1970

Nhưng nếu bạn đặt múi giờ là (UTC +8: 00) Bắc Kinh, Trùng Khánh, HongKong, Urumq, bạn sẽ nhận được:

Thu Jan 01 08:00:00 CST 1970

Java lấy dấu thời gian, sau đó hiển thị thông tin ngày và giờ theo múi giờ.

Để giới thiệu về cách Java hiển thị thông tin ngày và giờ ở các múi giờ khác nhau, cách sắp xếp thông tin thời gian rất dễ dàng. Bạn nên lấy tem thời gian và tính đến múi giờ khi cắt thông tin thời gian. Sau đó, bạn có thể tạo một đối tượng Date mới với dấu thời gian cắt (chúng ta có thể gọi nó là dấu ngày), java sẽ bù múi giờ khi hiển thị thông tin ngày.

Như ở múi 8 phía Đông (giờ Bắc Kinh), giờ Bắc Kinh sớm hơn 8 giờ so với GMT, vì vậy bạn nên trừ đi 8 giờ khi thực hiện thao tác mô-đun. Có nghĩa là, bạn nên tính giờ GMT trước, sau đó Java sẽ thêm 8 giờ khi hiển thị thời gian dựa trên cài đặt múi giờ trên máy tính của bạn.


Vấn đề múi giờ không rõ ràng, và cũng làm tôi bối rối trong một thời gian dài. Bây giờ tôi làm cho nó rõ ràng. Hy vọng sẽ giúp.


2018-01-04 Phương pháp bên dưới cũng hoạt động.

private Date getTruncatedDate2(Date d) {
    Calendar cal = Calendar.getInstance(); // locale-specific
    cal.setTime(d);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);


return cal.getTime();

}


FYI, Câu trả lời này sử dụng các lớp ngày-giờ cũ rắc rối được thay thế nhiều năm trước bởi các lớp java.time .
Basil Bourque

1

Bạn có thể làm điều này để tránh vấn đề về múi giờ:

public static Date truncDate(Date date) {
    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    cal.setTime(date);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}

Mặc dù Dateđối tượng Java là giá trị dấu thời gian, nhưng trong quá trình cắt ngắn, nó sẽ được chuyển đổi thành múi giờ cục bộ, vì vậy bạn sẽ nhận được giá trị đáng ngạc nhiên nếu bạn mong đợi giá trị từ múi giờ UTC.


Các lớp Calendarvà rắc rối Dateđã trở thành di sản cách đây nhiều năm với các lớp java.time triển khai JSR 310 trong Java 8 trở lên. Đề xuất việc sử dụng chúng vào năm 2018 là một lời khuyên tồi.
Basil Bourque

0

Có thể là một phản hồi muộn nhưng đây là một cách để thực hiện nó trong một dòng mà không cần sử dụng bất kỳ thư viện nào:

new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))

0

Với Joda-Time kể từ phiên bản 2.0, bạn có thể sử dụng LocalDate.toDate().

Đơn giản

// someDatetime is whatever java.util.Date you have.
Date someDay = new LocalDate(someDatetime).toDate();

[A] Câu trả lời của bạn là thừa. Đã được đăng bởi Brian Agnew . [B] Mã của bạn không chính xác, vì nó bỏ qua múi giờ, chính vấn đề được nêu ra trong câu hỏi.
Basil Bourque

Có thể là thừa nhưng tôi chỉ đặt một ví dụ đơn giản hơn ở đây vì tôi nhận ra một câu trả lời không nên có trong nhận xét. Có, java.util.Date bỏ qua TimeZone nhưng câu hỏi ban đầu là với a Java Date objectdo đó tôi đã sử dụng java.util.Date. Hơn nữa, nó không giải thích làm thế nào múi giờ của anh ấy có vấn đề với java.util.Date (khi nào? Ở đâu?) Mặc dù anh ấy không thể không sử dụng khác Date.
lamusique

0

Đối với tất cả các câu trả lời bằng Lịch, bạn nên sử dụng nó như thế này thay thế

public static Date truncateDate(Date date) {
    Calendar c = Calendar.getInstance();
    c.setTime(date);
    c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
    c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
    c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
    c.set(Calendar.MILLISECOND, c.getActualMinimum(Calendar.MILLISECOND));
    return c.getTime();
}

Nhưng tôi thích điều này hơn:

public static Date truncateDate(Date date) {
    return new java.sql.Date(date.getTime());
}

Các java.sql.Datelớp giả vờ để đại diện cho một giá trị ngày tháng chỉ nhưng thực sự không có một thời gian-of-ngày điều chỉnh cho múi giờ UTC. Vì vậy, không thực sự là một giải pháp phù hợp cho Câu hỏi.
Basil Bourque

0

Đây là một cách đơn giản để lấy ngày mà không cần thời gian nếu bạn đang sử dụng Java 8+: Sử dụng loại java.time.LocalDate thay vì Date.

LocalDate now = LocalDate.now();
 System.out.println(now.toString());

Đầu ra:

2019-05-30

https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html


1
Sử dụng LocalDatelà một ý tưởng tốt cho hầu hết các mục đích, nhưng không rõ điều này sẽ hoạt động như thế nào với đầu vào từ câu hỏi , 2008-01-01 13:15:00.
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.