แปลงสตริงเป็นวัตถุปฏิทินใน Java


175

ฉันใหม่กับ Java ซึ่งมักจะทำงานกับ PHP

ฉันพยายามแปลงสตริงนี้:

จ. 14 มี.ค. 16:02:37 GMT 2011

เป็นวัตถุในปฏิทินเพื่อให้ฉันสามารถดึงปีและเดือนได้อย่างง่ายดาย:

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

มันจะเป็นความคิดที่ดีที่จะแยกมันด้วยตนเอง? ใช้วิธี substring หรือไม่

คำแนะนำใด ๆ ที่จะช่วยขอบคุณ!


คำตอบ:


397
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

หมายเหตุ: ตั้งค่าLocaleตามสภาพแวดล้อม / ความต้องการของคุณ


ดูสิ่งนี้ด้วย


onlineconversion.com/unix_time.htm นี่คือการแปลงเวลาออนไลน์ ค่าที่คำนวณโดยรหัส java และการแปลงออนไลน์นี้จะแตกต่างกัน ทำไม?? คุณช่วยกรุณาไปที่นี้ ขอบคุณ :)
Sachin J

6
โปรดทราบว่าสิ่งนี้จะสูญเสียข้อมูลเขตเวลา วัตถุปฏิทินจะมีเขตเวลาเริ่มต้นของระบบไม่ใช่ส่วนที่แยกวิเคราะห์
Cristian Vrabie

นี่ไม่ควรเป็นคำตอบที่ได้รับการยอมรับสูงสุด ตั้งแต่ Java 8 มีอยู่แล้วออกมานานกว่า 4 java.timeปีคำตอบที่ควรได้รับการปรับปรุงเพื่อให้การกล่าวถึง คำถาม / ข้อนี้เด่นมากใน google
Scolytus

18

TL; DR

วิธีการที่ทันสมัยใช้คลาส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

หลีกเลี่ยงคลาสวันและเวลาดั้งเดิม

วิธีที่ทันสมัยอยู่กับคลาส java.time คลาสวันที่และเวลาเก่าเช่นCalendarได้รับการพิสูจน์แล้วว่าออกแบบมาไม่ดีสับสนและมีปัญหา

กำหนดฟอร์แมตเตอร์แบบกำหนดเองเพื่อจับคู่สตริงอินพุตของคุณ

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

ZonedDateTimeแยกวิเคราะห์เป็น

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

คุณมีความสนใจในปีและเดือน คลาส java.time มีYearMonthคลาสสำหรับวัตถุประสงค์นั้น

YearMonth ym = YearMonth.from( zdt );

คุณสามารถสอบปากคำสำหรับหมายเลขปีและเดือนหากจำเป็น

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

แต่toStringวิธีการสร้างสตริงในรูปแบบISO 8601 มาตรฐาน

String output = ym.toString();

ใส่ทั้งหมดนี้เข้าด้วยกัน

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();

ถ่ายโอนข้อมูลไปยังคอนโซล

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

อินพุต: จ. 14 มี.ค. 16:02:37 GMT 2011

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

ym: 2011-03

รหัสสด

ดูรหัสนี้ทำงานใน IdeOne.com

การแปลง

หากคุณต้องมีCalendarวัตถุคุณสามารถแปลงเป็นGregorianCalendarวิธีการใหม่ที่ใช้ในคลาสเก่าได้

GregorianCalendar gc = GregorianCalendar.from( zdt );

เกี่ยวกับ java.time

java.timeกรอบถูกสร้างขึ้นใน Java 8 และต่อมา ชั้นเรียนเหล่านี้แย่งลำบากเก่ามรดกเรียนวันที่เวลาเช่นjava.util.Date, และCalendarSimpleDateFormat

Joda เวลาโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาให้คำแนะนำแก่การโยกย้ายไปยัง java.time

ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา Stack Overflow สำหรับตัวอย่างและคำอธิบายมากมาย สเปกJSR 310

จะรับคลาส java.time ได้ที่ไหน?

  • Java SE 8และ SE 9และใหม่กว่า
    • Built-in
    • เป็นส่วนหนึ่งของ Java API มาตรฐานที่มีการใช้งานแบบรวม
    • Java 9 เพิ่มคุณสมบัติและการแก้ไขเล็กน้อย
  • Java SE 6และ SE 7
    • มากของการทำงาน java.time จะกลับรังเพลิง Java 6 และ 7 ในThreeTen-ย้ายกลับ
  • Android

โครงการThreeTen-Extraขยาย java.time ด้วยคลาสเพิ่มเติม โครงการนี้เป็นพื้นฐานที่พิสูจน์ได้สำหรับการเพิ่มเติมในอนาคตไปยัง java.time คุณอาจพบว่าการเรียนที่มีประโยชน์บางอย่างที่นี่เช่นInterval, YearWeek, YearQuarterและอื่น ๆ อีกมากมาย


14

SimpleDateFormatดีฉันคิดว่ามันจะเป็นความคิดที่ดีที่จะทำซ้ำรหัสที่มีอยู่แล้วในปัจจุบันเช่นการเรียน

ในทางกลับกันโดยส่วนตัวฉันขอแนะนำให้หลีกเลี่ยงCalendarและDateทั้งหมดถ้าคุณสามารถและใช้Joda Timeแทนเป็น API วันที่และเวลาที่ออกแบบมาดีกว่า ตัวอย่างเช่นคุณจะต้องตระหนักว่าSimpleDateFormatจะไม่ด้ายปลอดภัยดังนั้นคุณอาจต้องด้ายชาวบ้านประสานหรืออินสแตนซ์ใหม่ทุกครั้งที่คุณใช้มัน parsers Joda และจัดรูปแบบเป็นด้ายปลอดภัย


ขอบคุณสำหรับข้อมูลของคุณฉันจะใช้ Joda ต่อไปในอนาคตดูเหมือนว่ามันจะมีประโยชน์มาก
Doug Molineux

@Jon Skeet Joda จะไม่ถอนการขายใน Android Joda มีค่าน้อยเว้นแต่คุณไม่จำเป็นต้องบันทึกวันที่และเวลา
Frank Zappa

@ Frankzappa: ฉันไม่เห็นด้วยกับสิ่งนั้น - คุณสามารถทำการคำนวณวันที่ / เวลาทั้งหมดใน Joda Time ได้ แต่จากนั้นแปลงเป็นประเภทอื่น ๆ
Jon Skeet

ขออภัยต้อง downvote คำตอบเก่าเกินไปมันเก่าเกินไปที่จะเป็นคำตอบอันดับสูงสุด วันนี้java.timeเป็นวิธีที่จะไป Basil Bourque ให้คำตอบที่ยอดเยี่ยม
Scolytus

2
@Scolytus: คำตอบยอดนิยม (และยอมรับ) มี 332 คะแนนเปรียบเทียบกับ 10 ในรายการนี้ ผมคิดว่าถ้าคุณไปรอบ downvoting ทุกคำตอบ + ทุบทุกสถิติเก่า 7 ที่มีทางออกที่ดีกว่าตอนนี้คุณจะวิ่งออกจาก downvotes ... (ผมเห็นว่าคำตอบเพราว่าเป็นสิ่งที่ดีและฉันได้ upvoted ที่.)
Jon Skeet

10

ไม่จำเป็นต้องสร้างปฏิทินใหม่ SimpleDateFormat ใช้ปฏิทินภายใต้

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();

(ฉันยังไม่สามารถแสดงความคิดเห็นได้นั่นเป็นเหตุผลที่ฉันสร้างคำตอบใหม่)


1
โซลูชันของคุณดูดี แต่มีข้อเสียสองประการ: 1. JavaDoc ไม่รับประกันว่าการทำงานจะเป็นไปตามที่คาดไว้ 2. อย่างน้อยสำหรับ Java 6 คุณจะพบพา ธ ที่บรรทัด 1353 ซึ่งมีการโคลนวัตถุปฏิทิน ดังนั้นจากนั้น! date.equals (cal.getTime ())
niels

5

SimpleDateFormatเยี่ยมมากโปรดทราบว่าHHแตกต่างจากhhเมื่อทำงานกับชั่วโมง HHจะกลับ 24 ชั่วโมงตามชั่วโมงและ hh จะกลับ 12 ชั่วโมงตามชั่วโมง

ตัวอย่างเช่นต่อไปนี้จะส่งคืนเวลา 12 ชั่วโมง:

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

ขณะนี้จะส่งคืนเวลา 24 ชั่วโมง:

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

4

แยกเวลาด้วยเขตเวลาZในรูปแบบสำหรับเขตเวลา

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();
}

เอาท์พุท: มันจะกลับมาเวลา UTC

1508899140000

ป้อนคำอธิบายรูปภาพที่นี่

yyyy-MM-dd'T'HH:mm:ssถ้าเราไม่ได้ตั้งค่าโซนเวลาในรูปแบบเช่น SimpleDateFormatจะใช้เขตเวลาที่ตั้งไว้Setting


3

ใช่มันเป็นการปฏิบัติที่ไม่ดีในการแยกวิเคราะห์ด้วยตัวคุณเอง ลองดูที่SimpleDateFormatมันจะเปลี่ยนสตริงเป็นวันที่และคุณสามารถตั้งค่าวันที่ให้เป็นอินสแตนซ์ปฏิทินได้


1

วิธีง่าย ๆ :

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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.