IT이야기

LocalDateTime을 사용하여 날짜를 해석/포맷하는 방법(자바 8)

cyworld 2022. 7. 25. 22:45
반응형

LocalDateTime을 사용하여 날짜를 해석/포맷하는 방법(자바 8)

Java 8은 날짜와 시간을 사용하기 위한 새로운 java.time API를 추가했습니다(JSR 310).

날짜와 시간을 문자열로 지정합니다(예:"2014-04-08 12:30"). 지정된 문자열에서 인스턴스를 가져오려면 어떻게 해야 합니까?

★★★★★★의 작업이 된 후LocalDateTime★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★LocalDateTime위와 방법?

해석 날짜 및 해석

「」를 LocalDateTimestatic 메서드를 사용할 수 있습니다.여기에는 문자열과 as 파라미터가 필요합니다.DateTimeFormatter날짜/시간 패턴을 지정하기 위해 사용합니다.

String str = "1986-04-08 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);

날짜 및 시간 형식 지정

하려면 , 「」를 합니다.LocalDateTime할 수 format()★★★★★★ 。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.of(1986, Month.APRIL, 8, 12, 30);
String formattedDateTime = dateTime.format(formatter); // "1986-04-08 12:30"

.DateTimeFormatter : : 사용합니다.DateTimeFormatter.ISO_DATE_TIME을 정하다LocalDateTime."1986-04-08T12:30:00".

parse() ★★★★★★★★★★★★★★★★★」format()는 모든 할 수 : "Date/Time" / "Manages").LocalDate ★★★★★★★★★★★★★★★★★」ZonedDateTime)

이 경우에도 하실 수 있습니다.LocalDate.parse() ★★★★★★★★★★★★★★★★★」LocalDateTime.parse() String 「패턴을 지정해 주세요」, 「」, 「」, 「」의 경우,StringISO-8601 형식입니다.

예를들면,

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);

String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);

출력,

Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30

를 사용합니다.DateTimeFormatter다른 날짜 패턴에 대처해야 할 경우에만요

예를 들어 다음 예에서는 dd MM uuu의 날짜(2자리), 달의 이름 세 글자(1월, 2월, 3월, ...) 및 4자리 연도를 나타냅니다.

DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
String anotherDate = "04 Aug 2015";
LocalDate lds = LocalDate.parse(anotherDate, dTF);
System.out.println(anotherDate + " parses to " + lds);

산출량

04 Aug 2015 parses to 2015-08-04

이 부분은 꼭 .DateTimeFormatter오브젝트는 양방향으로 입력과 포맷 출력을 모두 해석할 수 있습니다.

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
System.out.println(aLD + " formats as " + dTF.format(aLD));

산출량

2015-08-04 formats as 04 Aug 2015

(Formating and Parsing DateFormatter의 패턴 전체 목록 참조)

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3

   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000

   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

   p       pad next                    pad modifier      1

   '       escape for text             delimiter
   ''      single quote                literal           '
   [       optional section start
   ]       optional section end
   #       reserved for future use
   {       reserved for future use
   }       reserved for future use

위의 두 답변 모두 문자열 패턴에 대한 질문을 매우 잘 설명합니다.그러나 ISO 8601을 사용하는 경우에는 적용할 필요가 없습니다.DateTimeFormatterLocalDateTime:

LocalDateTime을 시간대 ISO8601 문자열로 변환

LocalDateTime ldt = LocalDateTime.now(); 
ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC); //you might use a different zone
String iso8601 = zdt.toString();

ISO8601 문자열에서 LocalDateTime으로 다시 변환

String iso8601 = "2016-02-14T18:32:04.150Z";
ZonedDateTime zdt = ZonedDateTime.parse(iso8601);
LocalDateTime ldt = zdt.toLocalDateTime();

날짜와 시간이 포함된 문자열을 특정 시점(Java는 "")Instant으로 해석하는 것은 매우 복잡합니다.Java는 여러 번 반복하여 이 문제를 해결하고 있습니다.최근에 나온 거java.time ★★★★★★★★★★★★★★★★★」java.time.chrono는 거의 모든 요구에 대응하고 있습니다(Time Dilation : 제외).

그러나 그 복잡성은 많은 혼란을 가져온다.

날짜 해석을 이해하는 열쇠는 다음과 같습니다.

Java는 왜 이렇게 많은 방법으로 날짜를 해석할 수 있을까요?

  1. 시간을 측정하는 시스템은 여러 가지가 있습니다.예를 들어, 일본의 역사적 달력은 각각의 천황이나 왕조의 통치 기간에서 유래되었다.그리고 예를 들어,UNIX 타임스탬프다행히 전 세계가 같은 것을 사용할 수 있었다.
  2. 과거에는 여러 가지 이유로 시스템이 전환되었습니다.예: 1582년 율리우스력에서 그레고리력으로.그래서 그 이전의 '서양' 날짜는 다르게 다뤄질 필요가 있다.
  3. 그리고 물론 변화는 즉시 일어나지 않았다.달력은 일부 종교와 다른 식이요법을 믿는 유럽의 다른 지역들에서 나왔기 때문에, 예를 들어 독일은 1700년까지 바꾸지 않았다.

왜...★★★★★★★★★★★★★★★★★★?LocalDateTime,ZonedDateTime

  1. 시간대가 있어요.시간대는 기본적으로 언제 시간 오프셋을 가질지에 대한 동일한 규칙을 따르는 지구 표면의 "스트라이프"*[1]입니다.여기에는 여름 시간 규칙이 포함됩니다.
    타임존은 시간이 지남에 따라 변화하며 주로 누가 누구를 정복하느냐에 따라 달라집니다.그리고 한 타임존의 규칙도 시간이 지남에 따라 바뀝니다.

  2. 시간 오프셋이 있습니다.시간대는 "Prague"와 같이 될 수 있지만 여름 시간 오프셋과 겨울 시간 오프셋이 있습니다.
    타임존을 포함한 타임스탬프를 취득했을 경우, 오프셋은, 그 해의 어느 부분에 해당하는가에 따라서 다릅니다.윤시간 동안 타임스탬프는 두 번의 다른 시간을 의미할 수 있으므로 추가 정보가 없으면 안정적으로 변환할 수 없습니다.
    주의: 타임스탬프란 "날짜 및/또는 시간을 포함하는 문자열(옵션으로 시간대 및/또는 시간 오프셋 포함)"을 의미합니다.

  3. 여러 시간대가 특정 기간 동안 동일한 시간 오프셋을 공유할 수 있습니다.예를 들어 GMT/UTC 시간대는 여름 시간 오프셋이 적용되지 않을 때 "런던" 시간대와 동일합니다.

조금 더 복잡해지려면(단, 사용 사례에는 그다지 중요하지 않습니다) 다음을 수행합니다.

  1. 소(小)2040-12-31 24:00:00을 사용하다에서는 이러한 데이터를 에 대한 수 있습니다예를 들어 Linux에서는 이러한 새 데이터를 포함하여 Java 패키지에 대한 정기적인 업데이트를 받을 수 있습니다.
  2. 갱신에서는, 이력 타임스탬프와 장래의 타임스탬프의 양쪽 모두에 대해서, 반드시 이전의 동작이 유지되는 것은 아닙니다.따라서 어떤 타임존의 변경을 중심으로2개의 타임스탬프를 해석하면 다른 버전의 소프트웨어에서 실행할 때 다른 결과가 나올 수 있습니다.이는 영향을 받는 타임존과 다른 타임존의 비교에도 적용됩니다.

    이로 인해 소프트웨어에 오류가 발생할 경우 UNIX 타임스탬프 등 복잡한 규칙이 없는 타임스탬프를 사용하는 것을 검토해 주십시오.

  3. 7시 때문에 미래의 날짜에 대해서는 정확하게 날짜를 변환할 수 없습니다.를 의 「」, 「」, 「」, 「」의 해석은 다음과 같습니다.8524-02-17 12:00:00의 parsing에서 몇 초 수 .

이를 위한 JDK의 API는 현재의 요구에 따라 진화했습니다.

  • 에는 Java만 .java.util.Date몇 년, 몇 달, 몇 일, 몇 시간이 있다고 가정하면 순진하게 접근한 것 같아요.이것은 빠르게 충분하지 않았다.
  • 에 꽤 , also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also also.java.sql.Date이치노
  • 쪽도 잘 않았기 에, 에서는CalendarAPI api 、 API api api api api 。
  • 이것은 여전히 시간대의 복잡성을 다루지 않았다.그러나 위의 API를 조합하는 것은 매우 어려운 작업이었습니다.Java 개발자들이 글로벌 웹 애플리케이션에 대한 작업을 시작하면서 Joda Time과 같은 대부분의 사용 사례를 대상으로 하는 라이브러리가 빠르게 인기를 끌었습니다.Joda Time은 약 10년간 사실상의 표준이었습니다.
  • 그러나 JDK는 Joda Time과 연동되지 않았기 때문에 작업이 다소 번거로웠습니다.그 때문에, JSR-310은, 이 문제에의 대처법에 대해 오랜 논의 끝에, 주로 Joda Time에 근거해 작성되었습니다.

에서의 java.time

타임스탬프를 해석할 유형을 결정합니다.

타임스탬프 스트링을 소비하는 경우는, 그 스트링에 포함되는 정보를 확인할 필요가 있습니다.이것이 중요한 포인트입니다.이 문제를 제대로 해결하지 못하면 "인스턴트를 만들 수 없음", "존 오프셋 누락", "알 수 없는 존 ID" 등과 같은 알 수 없는 예외가 발생합니다.

날짜와 시간이 기재되어 있습니까?

  1. 임오오??? ???
    은 「」입니다.+hh:mm 가끔, 트를, 끔,, 가,, 가 part, 가 part, part part,+00:00로 할 수 Z 타임 '줄루 타임',UTC[ Coordinated [Universal Time Coordinated]로 합니다.GMT이치노합니다.
    이러한 타임스탬프에는 를 사용합니다.

  2. 간대가? ??
    이러한 타임스탬프에는 를 사용합니다.
    은 역음음 음 zone 음음음음 구구구 구구구 zone구 구구 zone zone zone zone 。

    • 이름("Prague", "태평양 표준시", "PST") 또는
    • "zone ID" ("America/Los_Angeles", "Europe/London"), java.time으로 표시됩니다.ZoneId.

    시간대 목록은 ICAAN에 의해 지원되는 "TZ 데이터베이스"에 의해 컴파일됩니다.

    ★★★★★★★에 의하면ZoneId는 javadoc, ID로 지정할 Z오프셋을 지정합니다.이게 어떻게 실제 구역으로 매핑되는지 잘 모르겠어요. 스탬프가 시간 , 은 TZ의 대상이 .ResolverStyle해 주세요

  3. 다 없는 경우 누락된 컨텍스트가 가정되거나 무시됩니다.그리고 소비자가 결정해야 합니다.따라서 다음과 같이 해석해야 합니다.LocalDateTime로 변환되었습니다.OffsetDateTime누락된 정보를 추가합니다.

    • UTC 시간이라고 가정할 수 있습니다.UTC 오프셋0 시간을 추가합니다.
    • 변환이 이루어지는 장소의 시간이라고 가정할 수 있습니다.시스템의 표준 시간대를 추가하여 변환합니다.
    • 그냥 내버려두고 그대로 사용하셔도 됩니다.예를 들어, 두 번 비교 또는 추출하거나( 참조), 잘 모르고 중요하지 않은 경우(예: 로컬 버스 시간표)에 유용합니다.

부분 시간 정보

  • 「」를 할 수 .LocalDate,LocalTime,OffsetTime,MonthDay,Year , 「」YearMonth그만 둬요.

모든 정보를 알고 있는 경우는, 를 입수할 수 있습니다.또한 내부적으로는 이 변환에 사용됩니다.OffsetDateTime그리고.ZonedDateTime.

해석 방법을 알아내다

타임스탬프 문자열과 포맷을 모두 문자열로 해석할 수 있는 광범위한 문서가 있습니다.

미리 작성된 에서는 표준 타임스탬프 형식을 모두 커버해야 합니다.예를 들어.ISO_INSTANT해석할 수 있다2011-12-03T10:15:30.123457Z.

특수한 포맷이 있는 경우는, 독자적인 Date Time Formatter(파서이기도 한)를 작성할 수 있습니다.

private static final DateTimeFormatter TIMESTAMP_PARSER = new DateTimeFormatterBuilder()
   .parseCaseInsensitive()
   .append(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SX"))
   .toFormatter();

소스코드를 참조할 것을 권장합니다.DateTimeFormatter그리고 어떻게 그것을 만들 것인가에 대한 영감을 얻습니다.DateTimeFormatterBuilder거기 있는 김에, 여기도 봐주세요.ResolverStyle형식 및 모호한 정보에 대해 파서가 LENTERANCE인지 SMART인지 STRICT인지를 제어합니다.

Temporal Accessor(Temporal Accessor)

이제, 빈번한 실수는 복잡성에 대해 살펴보는 것입니다.TemporalAccessor이것은 개발자들이 어떻게 작업하는 데 익숙했는지에서 비롯됩니다.SimpleDateFormatter.parse(String).맞다,DateTimeFormatter.parse("...")주다TemporalAccessor.

// No need for this!
TemporalAccessor ta = TIMESTAMP_PARSER.parse("2011-... etc");

그러나 이전 섹션의 지식을 바탕으로 필요한 유형을 쉽게 해석할 수 있습니다.

OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z", TIMESTAMP_PARSER);

실제로 이 기능을 사용할 필요는 없습니다.DateTimeFormatter어느 하나.해석하는 유형에는parse(String)방법들.

OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z");

에 관하여TemporalAccessor문자열에 어떤 정보가 있는지 막연하게 알고 런타임에 결정하려는 경우 사용할 수 있습니다.

당신의 영혼에 이해의 빛을 비추고 싶습니다.

주의: 백포트가 있습니다.java.timeJava 6 및 7: ThreeTen-Backport로 이동합니다.Android의 경우 ThreeTenABP를 탑재하고 있습니다.

[1] 줄무늬뿐만 아니라 이상한 극단도 있습니다.예를 들어, 일부 인접 태평양 섬에는 +14:00 및 -11:00 시간대가 있습니다.즉, 한 섬에는 5월 3일 오후 1시가 있고, 멀지 않은 다른 섬에는 4월 12일 오후 30시가 있다는 것입니다(정확하게 계산하면 :)

필요한 형식으로 현재 UTC 시간 가져오기

// Current UTC time
        OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

        // GET LocalDateTime 
        LocalDateTime localDateTime = utc.toLocalDateTime();
        System.out.println("*************" + localDateTime);

        // formated UTC time
        DateTimeFormatter dTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        System.out.println(" formats as " + dTF.format(localDateTime));

        //GET UTC time for current date
        Date now= new Date();
        LocalDateTime utcDateTimeForCurrentDateTime = Instant.ofEpochMilli(now.getTime()).atZone(ZoneId.of("UTC")).toLocalDateTime();
        DateTimeFormatter dTF2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        System.out.println(" formats as " + dTF2.format(utcDateTimeForCurrentDateTime));

또 하나 주의할 점LocalDateTime.parse날짜 포맷 문자만 있는 커스텀포메터에서는 사용할 수 없습니다.uuuuMMdd이 경우,LocalDate.parse대신.예를 들어 다음과 같습니다.

String s = "20210223";
        
// ok
LocalDate.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd"));
        
// java.time.format.DateTimeParseException
LocalDateTime.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd")); 

두 가지 질문을 받겠습니다.예제 문자열"2014-04-08 12:30"

지정된 문자열에서 LocalDateTime 인스턴스를 가져오려면 어떻게 해야 합니까?

import java.time.format.DateTimeFormatter
import java.time.LocalDateTime

final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")

// Parsing or conversion
final LocalDateTime dt = LocalDateTime.parse("2014-04-08 12:30", formatter)

dt모든 날짜-시간 관련 작업을 허용해야 합니다.

그런 다음 LocalDateTime 인스턴스를 동일한 형식의 문자열로 다시 변환하려면 어떻게 해야 합니까?

final String date = dt.format(formatter)

정답은 다 좋아요.Java8+ 에는, 타임 존의 해석 및 포맷에 관한 다음의 패턴이 있습니다.V,z,O,X,x,Z.

다음은 설명서의 규칙에 따라 해석하기 위한 입니다.

   Symbol  Meaning                     Presentation      Examples
   ------  -------                     ------------      -------
   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

하지만 포맷은 어떨까요?여기 날짜 샘플이 있습니다(가정)ZonedDateTime)는, 다른 포맷의 패턴에 대해서, 다음의 패턴의 동작을 나타냅니다.

// The helper function:
static void printInPattern(ZonedDateTime dt, String pattern) {
    System.out.println(pattern + ": " + dt.format(DateTimeFormatter.ofPattern(pattern)));
}        

// The date:
String strDate = "2020-11-03 16:40:44 America/Los_Angeles";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzzz");
ZonedDateTime dt = ZonedDateTime.parse(strDate, format);
// 2020-11-03T16:40:44-08:00[America/Los_Angeles]

// Rules:
// printInPattern(dt, "V");     // exception!
printInPattern(dt, "VV");       // America/Los_Angeles
// printInPattern(dt, "VVV");   // exception!
// printInPattern(dt, "VVVV");  // exception!
printInPattern(dt, "z");        // PST
printInPattern(dt, "zz");       // PST
printInPattern(dt, "zzz");      // PST
printInPattern(dt, "zzzz");     // Pacific Standard Time
printInPattern(dt, "O");        // GMT-8
// printInPattern(dt, "OO");    // exception!
// printInPattern(dt, "OO0");   // exception!
printInPattern(dt, "OOOO");     // GMT-08:00
printInPattern(dt, "X");        // -08
printInPattern(dt, "XX");       // -0800
printInPattern(dt, "XXX");      // -08:00
printInPattern(dt, "XXXX");     // -0800
printInPattern(dt, "XXXXX");    // -08:00
printInPattern(dt, "x");        // -08
printInPattern(dt, "xx");       // -0800
printInPattern(dt, "xxx");      // -08:00
printInPattern(dt, "xxxx");     // -0800
printInPattern(dt, "xxxxx");    // -08:00
printInPattern(dt, "Z");        // -0800
printInPattern(dt, "ZZ");       // -0800
printInPattern(dt, "ZZZ");      // -0800
printInPattern(dt, "ZZZZ");     // GMT-08:00
printInPattern(dt, "ZZZZZ");    // -08:00

양의 오프셋의 경우+부호 문자는 어디에나 사용된다.-now) 및 생략하지 않습니다.

이 우물은 새것을 위한 것이다.java.time타입을 지정합니다.java.util.Date또는java.util.Calendar- 모든 타입이 고장났기 때문에 동작하지 않는다(및 비권장이라고 표시되어 있으므로 사용하지 말아 주세요)

다음과 같은 여러 가지 날짜 형식의 형식을 다룰 수 있다는 것은 멋진 일이었습니다.

final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);

언급URL : https://stackoverflow.com/questions/22463062/how-to-parse-format-dates-with-localdatetime-java-8

반응형