2010-11-17 135 views
9

Tôi có một chuỗi trong mẫu yyyy-MM-dd hh: mm a và tôi có thể nhận đối tượng múi giờ riêng biệt trong đó chuỗi trên đại diện cho ngày tháng.Chuyển chuỗi thành ngày có múi giờ

Tôi muốn chuyển đổi định dạng này sang định dạng dưới đây. yyyy-MM-dd HH: mm: ss Z

Tôi có thể làm như thế nào?

+0

http://joda-time.sourceforge.net/ làm cho tất cả các thao tác ngày trong java dễ dàng hơn nhiều nhiều – NimChimpsky

+0

@Emil tôi đã biết tính năng này sau khi bạn nói :), Cảm ơn. – John

+1

FYI, dự án [Joda-Time] (http://www.joda.org/joda-time/) hiện đang ở [chế độ bảo trì] (https://en.wikipedia.org/wiki/Maintenance_mode), với nhóm cố vấn di chuyển đến các lớp [java.time] (http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html). –

Trả lời

5

Sử dụng SimpleDateFormat

String string1 = "2009-10-10 12:12:12 "; 
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z") 
sdf.setTimeZone(tz); 
Date date = sdf.parse(string1); 
+0

một số lần getID() trả về chuỗi như thế này "America/Argentina/Ushuaia". Vì vậy, làm thế nào tôi có thể sử dụng nó – John

+0

-1: điều này sẽ ném ParseException trên hầu hết các múi giờ. –

+0

@Michael Konietzka @shal Tôi nhanh chóng bỏ lỡ điều đó, đã cập nhật câu trả lời –

0

Tạo một thể hiện mới của SimpleDateFormat sử dụng mô hình ngày của bạn. Sau đó, bạn có thể gọi phương thức phân tích cú pháp của nó là chuyển đổi các chuỗi ngày thành một đối tượng java.util.Date đối tượng .

16

Bạn có thể sử dụng SimpleDateFormat với yyyy-MM-dd HH:mm:ss và thiết lập một cách rõ ràng TimeZone:

public static Date getSomeDate(final String str, final TimeZone tz) 
    throws ParseException { 
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm a"); 
    sdf.setTimeZone(tz); 
    return sdf.parse(str); 
} 

/** 
* @param args 
* @throws IOException 
* @throws InterruptedException 
* @throws ParseException 
*/ 
public static void main(final String[] args) throws ParseException { 
    final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); 
    System.out.println(sdf.format(getSomeDate(
     "2010-11-17 01:12 pm", TimeZone.getTimeZone("Europe/Berlin")))); 
    System.out.println(sdf.format(getSomeDate(
     "2010-11-17 01:12 pm", TimeZone.getTimeZone("America/Chicago")))); 
} 

In ra:

2010-11-17 13:12:00 +0100

2010- 11-17 20:12:00 +0100

Cập nhật 2010/12/01: Nếu bạn muốn in một cách rõ ràng TimeZone đặc biệt, thiết lập nó trong SimpleDateFormat:

sdf.setTimeZone(TimeZone .getTimeZone("IST")); 
System.out.println(sdf.format(getSomeDate(
    "2010-11-17 01:12 pm", TimeZone.getTimeZone("IST")))); 

nào in 2010-11-17 13:12:00 +0530

+0

Cảm ơn Mr.Michael, Ngày & giờ được thay đổi theo Timezone.Note xuống +100, nó không thay đổi thời gian bù đắp TIMEZONE – John

+0

@shal : Xin lỗi, tôi không hiểu câu thứ hai của bạn. Bạn có nghĩ rằng có điều gì đó không ổn? –

+0

@ Michael, tôi nói thời gian đang được chuyển đổi đúng cách nhưng thấy phần "Z" trong giá trị ngày in "+0100" nó không thay đổi.Ví dụ: nếu tôi đang chuyển đổi ngày từ GMT sang IST thì " Z "một phần của ngày được chuyển đổi phải là" +0530 ". – John

0

Chắc chắn, định dạng mà thông thường được sử dụng sẽ được của một hình thức 2014-10-05T15:23:01Z (TZ)

Đối với một trong đó có sử dụng mã này

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); 
String dateInString = "2014-10-05T15:23:01Z"; 

try { 

    Date date = formatter.parse(dateInString.replaceAll("Z$", "+0000")); 
    System.out.println(date); 

} catch (ParseException e) { 
    e.printStackTrace(); 
} 

Đầu ra của nó sẽ là Sun Oct 05 20:53:01 IST 2014

Tuy nhiên, tôi không chắc tại sao chúng tôi phải thay thếTất cả "Z" nếu bạn không thêm thay thếTất cả chương trình sẽ không thành công.

4

tl; dr

LocalDateTime.parse( // Parse string as value without time zone. 
    "2017-01-23 12:34 PM" , 
    DateTimeFormatter.ofPattern("uuuu-MM-dd hh:mm a") 
).atZone(ZoneId.of("America/Montreal")) // Assign time zone. 
.toString()    // Generate string: 2017-01-23T17:34:00Z 
.replace("T" , " ") // Substitute SPACE for 'T' in middle. 
.replace("Z" , " Z") // Insert SPACE before 'Z'. 

Tránh thừa lớp ngày thời gian

Các câu trả lời khác sử dụng các lớp rắc rối cũ ngày-thời gian (Date, Calendar, vv), bây giờ di sản, thay thế bởi sự các lớp java.time.

LocalDateTime

Tôi có một chuỗi trong mô hình hh yyyy-MM-dd: mm a

một chuỗi đầu vào như vậy thiếu bất kỳ dấu hiệu của bù đắp-từ-UTC hoặc múi giờ. Vì vậy, chúng tôi phân tích cú pháp là LocalDateTime.

Xác định mẫu định dạng để khớp với thông tin nhập của bạn với đối tượng DateTimeFormatter.

String input = "2017-01-23 12:34 PM" ; 
DateTimeFormatter f = DateTimeFormatter.ofPattern("uuuu-MM-dd hh:mm a"); 
LocalDateTime ldt = LocalDateTime.parse(input , f); 

ldt.toString(): 2017-01-23T12: 34

Lưu ý rằng một LocalDateTimekhông một thời điểm cụ thể, chỉ có một ý tưởng mơ hồ về một loạt các khoảnh khắc tốt . Ví dụ, một vài phút sau nửa đêm ở Paris Pháp vẫn là "ngày hôm qua" ở Montréal Canada. Vì vậy, không có bối cảnh của một múi giờ như Europe/Paris hoặc America/Montreal, chỉ cần nói "một vài phút sau nửa đêm" không có ý nghĩa.

ZoneId

và tôi có thể nhận được các đối tượng múi giờ riêng biệt, trong đó các chuỗi trên đại diện cho ngày tháng.

Múi giờ được thể hiện bằng lớp ZoneId.

Chỉ định proper time zone name ở định dạng continent/region, chẳng hạn như America/Montreal, Africa/Casablanca hoặc Pacific/Auckland. Không bao giờ sử dụng từ viết tắt 3-4 ký tự như EST hoặc IST vì chúng là không múi giờ thực, không được chuẩn hóa và thậm chí không độc đáo (!).

ZoneId z = ZoneId.of("America/Montreal"); 

ZonedDateTime

Áp dụng ZoneId để có được một ZonedDateTime mà thực sự là một điểm trên dòng thời gian, một thời điểm cụ thể trong lịch sử.

ZonedDateTime zdt = ldt.atZone(z); 

zdt.toString(): 2017-01-23T12: 34-05: 00 [America/Montreal]

Instant

Tôi muốn chuyển đổi này để định dạng dưới đây. yyyy-MM-dd HH: mm: ss Z

Đầu tiên, hãy biết rằng một ký tự chữ Z là viết tắt của Zulu và phương tiện UTC. Nói cách khác, một số offset-from-UTC trong số 0 giờ, +00:00.

Lớp Instant đại diện cho một thời điểm trên dòng thời gian ở UTC với độ phân giải nanoseconds (tối đa chín (9) chữ số thập phân).

Bạn có thể trích xuất đối tượng Instant từ một số ZonedDateTime.

Instant instant = zdt.toInstant(); // Extracting the same moment but in UTC. 

Để tạo một chuỗi trong định dạng chuẩn ISO 8601, chẳng hạn như 2017-01-22T18:21:13.354Z, gọi toString. Định dạng chuẩn không có dấu cách, sử dụng số T để tách ngày tháng theo năm từ phút thứ hai và thêm Z theo phương thức kinh điển để bù trừ số không.

String output = instant.toString(); 

instant.toString(): 2017-01-23T17: 34: 00Z

tôi khuyên bạn sử dụng định dạng tiêu chuẩn bất cứ khi nào có thể. Nếu bạn nhấn mạnh vào việc sử dụng dấu cách như trong định dạng mong muốn đã nêu của bạn, hãy xác định mẫu định dạng của riêng bạn trong đối tượng DateTimeFormatter hoặc chỉ thực hiện thao tác chuỗi trên đầu ra của Instant::toString.

String output = instant.toString() 
         .replace("T" , " ") // Substitute SPACE for T. 
         .replace("Z" , " Z"); // Insert SPACE before Z. 

đầu ra: 2017/01/23 17:34:00 Z

Hãy thử code live at IdeOne.com này.


Về java.time

Khung java.time được xây dựng vào Java 8 và sau đó. Các lớp này thay thế các lớp học ngày giờ legacy phiền hà cũ như java.util.Date, Calendar, & SimpleDateFormat.

Dự án Joda-Time, hiện đang ở maintenance mode, khuyên di chuyển đến các lớp java.time.

Để tìm hiểu thêm, hãy xem Oracle Tutorial. 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 lấy các lớp java.time?

Dự án mở rộng ThreeTen-Extra 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 những bổ sung có thể có trong tương lai vào java.time. Bạn có thể tìm thấy một số lớp học hữu ích tại đây như Interval, YearWeek, YearQuartermore.

Các vấn đề liên quan