Chuyển đổi chuỗi thành đối tượng lịch trong Java


174

Tôi mới sử dụng Java, thường làm việc với PHP.

Tôi đang cố gắng chuyển đổi chuỗi này:

Thứ Hai 14 tháng 3 16:02:37 GMT 2011

Vào Đối tượng Lịch để tôi có thể dễ dàng kéo Năm và Tháng như thế này:

String yearAndMonth = cal.get(Calendar.YEAR)+cal.get(Calendar.MONTH);

Nó sẽ là một ý tưởng tồi để phân tích nó bằng tay? Sử dụng phương pháp chuỗi con?

Mọi lời khuyên sẽ giúp cảm ơn!


Câu trả lời:


396
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done

lưu ý: đặt Localetheo môi trường / yêu cầu của bạn


Xem thêm


onlineconversion.com/unix_time.htmlm . Đây là công cụ chuyển đổi dấu thời gian trực tuyến. Giá trị được tính bằng mã java và chuyển đổi trực tuyến này sẽ khác nhau. Tại sao?? Bạn có thể vui lòng đi qua đây Cảm ơn :)
Sachin J

6
Lưu ý rằng điều này làm mất thông tin múi giờ. Đối tượng Lịch sẽ có TimeZone mặc định của hệ thống chứ không phải phân tích cú pháp.
Cristian Vrabie

Đây không phải là câu trả lời hàng đầu / được chấp nhận nữa. Vì Java 8 đã ra mắt được hơn 4 năm nên câu trả lời cần được cập nhật để đề cập java.time. Q / A này xuất hiện khá nổi bật trên google.
Scolytus

18

tl; dr

Cách tiếp cận hiện đại sử dụng các lớp java.time .

YearMonth.from(
    ZonedDateTime.parse( 
        "Mon Mar 14 16:02:37 GMT 2011" , 
        DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" )
     )
).toString()

2011/03

Tránh các lớp học thời gian kế thừa

Cách hiện đại là với các lớp java.time. Các lớp thời gian cũ như Calendarđã được chứng minh là được thiết kế kém, khó hiểu và rắc rối.

Xác định một trình định dạng tùy chỉnh để khớp với đầu vào chuỗi của bạn.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );

Phân tích như một ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

Bạn quan tâm đến năm và tháng. Các lớp java.time bao gồm YearMonthlớp cho mục đích đó.

YearMonth ym = YearMonth.from( zdt );

Bạn có thể thẩm vấn số năm và tháng nếu cần.

int year = ym.getYear();
int month = ym.getMonthValue();

Nhưng toStringphương thức tạo ra một chuỗi ở định dạng ISO 8601 tiêu chuẩn .

String output = ym.toString();

Đặt tất cả những thứ này lại với nhau.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
YearMonth ym = YearMonth.from( zdt );
int year = ym.getYear();
int month = ym.getMonthValue();

Đổ vào bàn điều khiển.

System.out.println( "input: " + input );
System.out.println( "zdt: " + zdt );
System.out.println( "ym: " + ym );

đầu vào: Mon Mar 14 16:02:37 GMT 2011

zdt: 2011 / 03-14T16: 02: 37Z [GMT]

ym: 2011/03

Mã sống

Xem mã này đang chạy trong IdeOne.com .

Chuyển đổi

Nếu bạn phải có một Calendarđối tượng, bạn có thể chuyển đổi sang GregorianCalendarsử dụng các phương thức mới được thêm vào các lớp cũ.

GregorianCalendar gc = GregorianCalendar.from( zdt );

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 java.time.

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

Nơi để có được các lớp java.time?

  • Java SE 8SE 9 trở lên
    • Được xây dựng trong.
    • Một phần của API Java tiêu chuẩn với việc triển khai đi kèm.
    • Java 9 thêm một số tính năng nhỏ và sửa lỗi.
  • Java SE 6 SE 7
    • Phần lớn chức năng java.time được chuyển ngược lại sang Java 6 & 7 trong ThreeTen-Backport .
  • Android

Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho các bổ sung có thể 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 .


14

Chà, tôi nghĩ sẽ là một ý tưởng tồi khi sao chép mã đã có trong các lớp như SimpleDateFormat .

Mặt khác, cá nhân tôi khuyên bạn nên tránh CalendarDatehoàn toàn nếu bạn có thể, và sử dụng Joda Time thay vào đó, như một API ngày và giờ được thiết kế tốt hơn nhiều. Ví dụ, bạn cần lưu ý rằng SimpleDateFormatkhông an toàn cho luồng, vì vậy bạn cần có các luồng cục bộ, đồng bộ hóa hoặc một thể hiện mới mỗi khi bạn sử dụng nó. Trình phân tích cú pháp và trình định dạng Joda luồng an toàn.


Cảm ơn sự đóng góp của bạn, tôi chắc chắn sẽ xem xét sử dụng Joda trong tương lai, có vẻ như nó có thể rất hữu ích
Doug Molineux

@Jon Skeet Joda sẽ không giải trừ trong Android. Joda có giá trị nhỏ trừ khi bạn không có nhu cầu tiết kiệm ngày và thời gian.
Frank Zappa

@FrankZappa: Tôi không đồng ý với điều đó - bạn có thể thực hiện tất cả các phép tính ngày / giờ của mình trong Joda Time, nhưng sau đó chuyển đổi sang các loại khác (có thể chỉ là chuỗi cho đơn giản) cho mục đích tuần tự hóa.
Jon Skeet

Xin lỗi, đã phải downvote, câu trả lời quá cũ, nó đã lỗi thời để là câu trả lời xếp hạng cao nhất. Hôm nay java.timelà con đường để đi, Basil Bourque cung cấp một câu trả lời tuyệt vời.
Scolytus

2
@Scolytus: Câu trả lời hàng đầu (và được chấp nhận) có 332 phiếu so với 10 phiếu cho câu hỏi này. Tôi nghĩ rằng nếu bạn đi vòng quanh hạ cấp cứ sau 7 câu trả lời cũ có giải pháp tốt hơn bây giờ, bạn sẽ hết lượt ... (Tôi đồng ý rằng câu trả lời của Basil là tốt, và tôi đã đánh giá cao điều đó.)
Jon Skeet

10

Không cần tạo Lịch mới, SimpleDateFormat đã sử dụng Lịch bên dưới.

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.EN_US);
Date date = sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done
Calendar cal = sdf.getCalendar();

(Tôi chưa thể nhận xét, đó là lý do tại sao tôi tạo câu trả lời mới)


1
Giải pháp của bạn có vẻ thanh lịch, nhưng có hai nhược điểm: 1. JavaDoc không đảm bảo rằng hành vi đó, như mong đợi. 2. Ít nhất đối với Java 6, bạn tìm thấy một đường dẫn ở dòng 1353 nơi đối tượng lịch được nhân bản. Vì vậy, sau đó! Date.equals (cal.getTime ()).
cháu gái

5

SimpleDateFormatlà tuyệt vời, chỉ cần lưu ý HHlà khác với hhkhi làm việc với giờ. HHsẽ trả lại 24 giờ dựa trên giờ và hh sẽ trả lại 12 giờ dựa trên giờ.

Ví dụ: sau đây sẽ trả về thời gian 12 giờ:

SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");

Trong khi điều này sẽ trở lại thời gian 24 giờ:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

4

Phân tích thời gian với múi giờ, Ztheo mẫu dành cho múi giờ

String aTime = "2017-10-25T11:39:00+09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
try {
    Calendar cal = Calendar.getInstance();
    cal.setTime(sdf.parse(aTime));
    Log.i(TAG, "time = " + cal.getTimeInMillis()); 
} catch (ParseException e) {
    e.printStackTrace();
}

Đầu ra: nó sẽ trả về thời gian UTC

1508899140000

nhập mô tả hình ảnh ở đây

Nếu chúng ta không đặt múi giờ theo mẫu yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatsẽ sử dụng múi giờ đã đặtSetting


3

Vâng, nó sẽ là thực hành xấu để phân tích nó. Hãy xem SimpleDateFormat , nó sẽ biến Chuỗi thành Ngày và bạn có thể đặt Ngày thành phiên bản Lịch.


1

Phương pháp đơn giản:

public Calendar stringToCalendar(String date, String pattern) throws ParseException {
    String DEFAULT_LOCALE_NAME = "pt";
    String DEFAULT_COUNTRY = "BR";
    Locale DEFAULT_LOCALE = new Locale(DEFAULT_LOCALE_NAME, DEFAULT_COUNTRY);
    SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
    Date d = format.parse(date);
    Calendar c = getCalendar();
    c.setTime(d);
    return c;
}
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.