Phân tích cú pháp chuỗi thành ngày tháng với định dạng khác nhau trong Java


91

Tôi muốn chuyển đổi Stringsang Datecác định dạng khác nhau.

Ví dụ,

Tôi nhận được từ người dùng,

String fromDate = "19/05/2009"; // i.e. (dd/MM/yyyy) format

Tôi muốn chuyển đổi nó fromDatethành một đối tượng Date của "yyyy-MM-dd"định dạng

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


2
Đối tượng Date không có định dạng, nó chỉ là một số đại diện cho ngày tháng. Ngày có thể được biểu thị bằng Chuỗi có định dạng "yyyy-MM-dd".
user85421

Câu trả lời:


181

Hãy nhìn vào SimpleDateFormat. Mã có dạng như sau:

SimpleDateFormat fromUser = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd");

try {

    String reformattedStr = myFormat.format(fromUser.parse(inputString));
} catch (ParseException e) {
    e.printStackTrace();
}

1
thay vì nhận định dạng chuỗi, tôi có thể nhận đầu ra ở Dateđịnh dạng không?
Rachel

4
@Rachel: Chắc chắn, chỉ cần sử dụng parsevà không tiếp tục format. parsephân tích cú pháp một chuỗi thành một ngày.
Michael Myers

3
Nhưng parsemang lại cho tôi trong date formatkhi Fri Jan 06 00:01:00 EST 2012nhưng nó cần ở 2012-01-06định dạng ngày
Rachel

1
@Rachel đó là bởi vì khi bạn gọi System.out.println(anyDateObject)phương thức toString () mặc định được gọi được cho là in ở định dạng đó, ví dụ Fri Jan 06 00:01:00 EST 2012. Bạn cần ghi đè nó cho phù hợp với nhu cầu của mình.
KNU

3
FYI, các lớp date-time cũ rắc rối như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là kế thừa , được thay thế bởi các lớp java.time được tích hợp trong Java 8 & Java 9. Xem Hướng dẫn của Oracle .
Basil Bourque

13

tl; dr

LocalDate.parse( 
    "19/05/2009" , 
    DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) 
)

Chi tiết

Các câu trả lời khác với java.util.Date, java.sql.DateSimpleDateFormatgiờ đây là lỗi thời.

LocalDate

Cách hiện đại để thực hiện date-time là làm việc với các lớp java.time, cụ thể là LocalDate. Các LocalDatelớp đại diện cho một giá trị ngày tháng chỉ mà không cần thời gian của ngày và không có múi giờ.

DateTimeFormatter

Để phân tích cú pháp hoặc tạo một Chuỗi đại diện cho giá trị ngày-giờ, hãy sử dụng DateTimeFormatterlớp.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
LocalDate ld = LocalDate.parse( "19/05/2009" , f );

Không kết hợp đối tượng ngày-giờ với một Chuỗi đại diện cho giá trị của nó. Một đối tượng ngày thời gian không định dạng , trong khi một String hiện. Đối tượng ngày-giờ, chẳng hạn LocalDate, có thể tạo Chuỗi để biểu thị giá trị bên trong của nó, nhưng đối tượng ngày-giờ và Chuỗi là các đối tượng riêng biệt riêng biệt.

Bạn có thể chỉ định bất kỳ định dạng tùy chỉnh nào để tạo Chuỗi. Hoặc để java.time thực hiện công việc tự động bản địa hóa.

DateTimeFormatter f = 
    DateTimeFormatter.ofLocalizedDate( FormatStyle.FULL )
                     .withLocale( Locale.CANADA_FRENCH ) ;
String output = ld.format( f );

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

System.out.println( "ld: " + ld + " | output: " + output );

ld: 2009-05-19 | đầu ra: mardi 19 mai 2009

Xem thực tế trong IdeOne.com .


Giới thiệu về java.time

Khung java.time được tích hợp sẵn trong Java 8 trở lên. 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 triển khai theo 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 .


12

Sử dụng SimpleDateFormatlớp học:

private Date parseDate(String date, String format) throws ParseException
{
    SimpleDateFormat formatter = new SimpleDateFormat(format);
    return formatter.parse(date);
}

Sử dụng:

Date date = parseDate("19/05/2009", "dd/MM/yyyy");

Để hiệu quả, bạn muốn lưu trữ các định dạng của mình trong một bản đồ băm. Bản đồ băm là một thành viên tĩnh của lớp sử dụng của bạn.

private static Map<String, SimpleDateFormat> hashFormatters = new HashMap<String, SimpleDateFormat>();

public static Date parseDate(String date, String format) throws ParseException
{
    SimpleDateFormat formatter = hashFormatters.get(format);

    if (formatter == null)
    {
        formatter = new SimpleDateFormat(format);
        hashFormatters.put(format, formatter);
    }

    return formatter.parse(date);
}

9
BẮT ĐẦU !! Ý tưởng thì tốt nhưng thực hiện thì không. DateFormats không được lưu trữ tĩnh, vì chúng không an toàn cho chuỗi! Nếu chúng được sử dụng từ nhiều hơn một luồng (và điều này luôn tiềm ẩn rủi ro với tĩnh). FindBugs chứa một công cụ dò tìm cho điều này (tôi đã tình cờ đóng góp ban đầu, sau khi tôi bị cắn. Xem dschneller.blogspot.com/2007/04/… :-))
Daniel Schneller

Mục nhập blog của bạn là một bài đọc thú vị :-) Điều gì sẽ xảy ra nếu chính phương thức parseDate mà tôi đã đồng bộ hóa? Tuy nhiên, vấn đề là nó có thể sẽ làm chậm mã ...
Agora

1
Miễn là phương thức parseDate là phương thức duy nhất truy cập vào bản đồ, việc đồng bộ hóa nó sẽ hoạt động. Tuy nhiên, điều này - như bạn nói - tạo ra một nút thắt cổ chai.
Daniel Schneller

8

Chuyển đổi ngày chuỗi thành java.sql.Date

String fromDate = "19/05/2009";
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
java.util.Date dtt = df.parse(fromDate);
java.sql.Date ds = new java.sql.Date(dtt.getTime());
System.out.println(ds);//Mon Jul 05 00:00:00 IST 2010


3

Mặc dù SimpleDateFormatthực sự sẽ hoạt động cho nhu cầu của bạn, ngoài ra, bạn có thể muốn xem Joda Time , đây rõ ràng là cơ sở cho thư viện Date được làm lại trong Java 7. Mặc dù tôi chưa sử dụng nó nhiều nhưng tôi chẳng nghe thấy gì ngoài những điều tốt đẹp về nó và nếu bạn thao túng ngày tháng rộng rãi trong các dự án của mình thì điều đó có thể đáng xem xét.


1

Cách đơn giản để định dạng ngày và chuyển đổi thành chuỗi

    Date date= new Date();

    String dateStr=String.format("%td/%tm/%tY", date,date,date);

    System.out.println("Date with format of dd/mm/dd: "+dateStr);

đầu ra: Ngày có định dạng dd / mm / dd: 21/10/2015


1

Một Dateđối tượng không có định dạng , nó là một biểu diễn. Ngày có thể được trình bày bằng một Stringvới định dạng bạn thích .

Ví dụ: " yyyy-MM-dd", " yy-MMM-dd", " dd-MMM-yy" và v.v.

Để đạt được điều này, bạn có thể sử dụng SimpleDateFormat

Thử cái này,

        String inputString = "19/05/2009"; // i.e. (dd/MM/yyyy) format

        SimpleDateFormat fromUser = new SimpleDateFormat("dd/MM/yyyy"); 
        SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd");

        try {
            Date dateFromUser = fromUser.parse(inputString); // Parse it to the exisitng date pattern and return Date type
            String dateMyFormat = myFormat.format(dateFromUser); // format it to the date pattern you prefer
            System.out.println(dateMyFormat); // outputs : 2009-05-19

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

Kết quả này: 2009-05-19


1

Giả sử rằng bạn có một chuỗi như thế này:

String mDate="2019-09-17T10:56:07.827088"

Bây giờ chúng tôi muốn thay đổi Stringđịnh dạng ngày và giờ riêng biệt này trong JavaKotlin .

JAVA:

chúng tôi có một phương pháp cho ngày trích xuất :

public String getDate() {
    try {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
        Date date = dateFormat.parse(mDate);
        dateFormat = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
        return dateFormat.format(date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return null;
}

Return đây là: 17/09/2019

Và chúng tôi có phương pháp cho thời gian trích xuất :

public String getTime() {

    try {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
        Date date = dateFormat.parse(mCreatedAt);
        dateFormat = new SimpleDateFormat("h:mm a", Locale.US);
        return dateFormat.format(date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return null;
}

Returnđây là: 10:56 sáng

KOTLIN:

chúng ta có một hàm cho ngày trích xuất :

fun getDate(): String? {

    var dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US)
    val date = dateFormat.parse(mDate!!)
    dateFormat = SimpleDateFormat("MM/dd/yyyy", Locale.US)
    return dateFormat.format(date!!)
}

Return đây là: 17/09/2019

Và chúng tôi có phương pháp cho thời gian trích xuất :

fun getTime(): String {

    var dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US)
    val time = dateFormat.parse(mDate!!)
    dateFormat = SimpleDateFormat("h:mm a", Locale.US)
    return dateFormat.format(time!!)
}

Returnđây là: 10:56 sáng


Xin đừng dạy những đứa trẻ sử dụng SimpleDateFormatlớp học đã lỗi thời và khét tiếng phiền phức . Ít nhất không phải là tùy chọn đầu tiên. Và không phải không có bất kỳ đặt trước. Ngày nay, chúng ta có rất nhiều thứ tốt hơn java.time, API ngày giờ hiện đại của Java và nó DateTimeFormatter. Cũng SimpleDateFormatkhông thể phân tích cú pháp 6 số thập phân trên giây (micro giây) một cách chính xác.
Ole VV

Khi tôi chạy đoạn mã thứ hai của bạn, tôi không nhận được 10:56 AMnhư bạn nói, nhưng thay vào đó 11:09 AM(được thử nghiệm trên Oracle jdk-11.0.3).
Ole VV

@ OleV.V. , Nếu một phương thức đã lỗi thời từ lâu, nó sẽ không được chấp nhận với một dòng trên đó là dấu hiệu, nếu một phương thức hoặc lớp không bị phản đối, chúng ta có thể sử dụng nó, tôi không nói đó là cách tốt nhất, có thể chúng ta có cách tốt hơn nhưng cách này rất đơn giản và dễ hiểu, nếu một phương pháp hoặc lớp đã già không có lý do rằng đó là phiền hà và sử dụng của DateTimeFormatterchúng ta cần phải minsdk 26hoặc cao hơn thì điều không tốt của nó
Milad salimi

@ OleV.V. Nhưng nhờ bình luận của bạn và về bình luận thứ hai của bạn tôi có thể nói rằng tôi kiểm tra xem nó nhiều lần trong hai Application và nó trở lại10:56 AM
Milad salimi

1
@ OleV.V. , Ok nhưng tôi sử dụng thư viện khi tôi không có cách nào hoặc API (thư viện) đó rất tốt hơn mã của tôi, bởi vì khi bạn thêm thư viện, bạn sẽ thêm một số mã vào dự án của mình mà có thể không được sử dụng và điều này là quá tải cho dự án, đây là cách tiếp cận của tôi và cách tiếp cận của bạn rất đáng nể đối với tôi.
milad salimi 19/09/19
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.