JavaRush /Java Blog /Random-KO /시간 및 날짜 작업을 위한 직관적이고 강력한 라이브러리가 마침내 Java(1부)에서 사용 가능해졌습니다...
theGrass
레벨 24
Саратов

시간 및 날짜 작업을 위한 직관적이고 강력한 라이브러리가 마침내 Java(1부)에서 사용 가능해졌습니다.

Random-KO 그룹에 게시되었습니다
Java는     마침내 날짜와 시간을 처리하는 직관적이고 안정적인 방법을 갖게 되었습니다. 날짜와 시간의 원칙은 많은 응용 프로그램에서 기본입니다. 생년월일, 대여 날짜, 이벤트 시간, 매장 영업 시간 등 다양한 사항은 모두 날짜 및 시간을 기준으로 하지만 Java SE는 이를 처리하는 편리한 방법을 제공하지 않았습니다. Java SE 8 부터 날짜 및 시간 작업을 위한 잘 구조화된 API를 제공하는 java.time 패키지 세트가 있었습니다.
배경
Java가 처음 출시되었을     때 버전 1.0 에서는 날짜 및 시간 작업을 위한 유일한 클래스는 java.util.Date 였습니다 . 개발자가 가장 먼저 알아차린 것은 "날짜"를 나타내지 않는다는 것입니다. 실제로 이는 1970년 1월 1일부터 측정된 밀리초 단위의 정확한 순간을 나타냅니다. 그러나 DatetoString() 메소드가 시스템의 Java 설정 에 지정된 시간대의 날짜와 시간을 표시한다는 사실을 기반으로 일부 개발자는 Date가 시간대와 작동할 수 있다고 잘못 결론을 내렸습니다. 이 클래스를 수정하는 것은 너무 어려운(또는 너무 게으른) 것으로 판명되어 버전 1.1 에서는 새로운 클래스인 java.util.Calendar 를 추가해야 했습니다 . 불행하게도 Calendar 클래스는 Date 클래스 보다 별로 좋지 않은 것으로 나타났습니다 . 다음은 구현 시 발생하는 문제의 작은 목록입니다.
  • 변하기 쉬운. 날짜 및 시간과 같은 클래스는 변경할 수 없어야 합니다.
  • 오프셋. 날짜의 연도는 1900년부터 시작하고 두 클래스의 월은 0부터 시작합니다.
  • 이름. Date는 실제로 "날짜"가 아니며 Calendar는 달력이 아닙니다.
  • 포맷. 형식 지정은 달력이 아닌 날짜에서만 작동하며 스레드로부터 안전하지 않습니다.
    2001년에 Joda-Time 프로젝트가 만들어졌습니다 . 그의 목표는 간단했습니다. Java 에서 날짜와 시간 작업을 위한 고품질 라이브러리를 만드는 것이었습니다 . 시간이 좀 걸렸지만 결국 버전 1.0 이 출시되었고 빠르게 큰 인기를 얻고 널리 사용되었습니다. 시간이 지남에 따라 개발자들은 유사한 편의 라이브러리를 JDK 의 일부로 제공할 것을 점점 더 요구했습니다 . 브라질의 Michael Nascimento Santos의 참여로 JSR-310 프로젝트가 시작되었습니다 . 이는 JDK 에서 날짜 및 시간 작업을 위한 새로운 API를 생성하고 통합하는 공식 프로세스입니다 .
검토
새로운 java.time API에는 5개의 패키지가 포함되어 있습니다.
  • java.time - 값을 저장할 객체가 포함된 기본 패키지
  • java.time.chrono - 다양한 달력에 대한 액세스 제공
  • java.time.format - 날짜 및 시간 형식 지정 및 인식
  • java.time.temporal - 하위 수준 라이브러리 및 고급 기능
  • java.time.zone - 시간대 작업을 위한 클래스
    대부분의 개발자는 기본 패키지와 형식을 주로 사용하며 아마도 java.time.temporal 도 사용할 것입니다 . 따라서 68개의 새로운 유형이 추가되었더라도 개발자는 그 중 약 1/3만 사용하게 됩니다.
날짜
LocalDate     클래스는 새 API 에서 가장 중요한 클래스 중 하나입니다 . 여기에는 날짜를 나타내는 변경할 수 없는 값이 포함되어 있습니다. 시간이나 시간대를 설정할 수 없습니다. "local"이라는 이름은 Joda-Time 에서 익숙할 수 있으며 원래는 ISO-8601 표준 에서 유래되었습니다 . 이는 정확히 시간대가 없다는 것을 의미합니다. 기본적으로 LocalDate는 "2014년 4월 5일"과 같은 날짜에 대한 설명입니다. 이 날짜의 실제 시간은 시간대에 따라 다릅니다. 예를 들어, 호주에서는 이 날짜가 런던보다 10시간 빠르며 샌프란시스코보다 18시간 빠릅니다. LocalDate 클래스 에는 일반적으로 필요한 모든 메서드가 있습니다. LocalDate date = LocalDate.of(2014, Month.JUNE, 10); int year = date.getYear(); // 2014 Month month = date.getMonth(); // Июнь int dom = date.getDayOfMonth(); // 10 DayOfWeek dow = date.getDayOfWeek(); // Вторник int len = date.lengthOfMonth(); // 30 (дней в Июне) boolean leap = date.isLeapYear(); // false (не високосный год)     이 예에서는 팩토리 메서드를 사용하여 생성된 날짜를 볼 수 있습니다(모든 생성자는 비공개입니다). 다음으로 객체에 일부 데이터를 요청합니다. MonthDayOfWeek 열거형은 코드를 더 읽기 쉽고 안정적으로 만들기 위해 설계되었습니다 . 다음 예에서는 날짜를 수정하는 방법을 살펴보겠습니다. 클래스는 불변이므로 결과는 새로운 객체가 되지만 원본 객체는 그대로 유지됩니다. LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.withYear(2015); // 2015-06-10 date = date.plusMonths(2); // 2015-08-10 date = date.minusDays(1); // 2015-08-09     이는 상대적으로 간단한 변경이지만 더 복잡한 날짜 수정이 필요한 경우가 많습니다. java.time API 에는 이를 위한 특별한 메커니즘인 TemporalAdjuster가 있습니다 . 그 목적은 날짜를 조작할 수 있는 내장 도구를 제공하는 것입니다. 예를 들어 해당 월의 마지막 날에 해당하는 객체를 가져오는 것입니다. 그 중 일부는 API 에 포함되어 있지만 직접 추가할 수도 있습니다. 수정자를 사용하는 것은 매우 쉽지만 정적 가져오기가 필요합니다. import static java.time.DayOfWeek.* import static java.time.temporal.TemporalAdjusters.* LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.with(lastDayOfMonth()); date = date.with(nextOrSame(WEDNESDAY));     수정자를 사용하면 코드가 크게 단순화됩니다. 수동으로 날짜를 조작하는 것을 보고 싶어하는 사람은 아무도 없습니다. 프로젝트에서 일종의 날짜 조작이 여러 번 발생하는 경우 고유한 수정자를 작성하면 팀에서 이를 이미 작성되고 테스트된 구성 요소로 사용할 수 있습니다.
시간 및 날짜를 ​​값으로 사용
LocalDate를 가치 있게     만드는 것이 무엇인지 이해하는 데 약간의 시간을 할애할 가치가 있습니다 . 값은 완전히 상호 교환 가능한 단순한 데이터 유형이므로 동일하면 객체의 정체성이 의미가 없게 됩니다. 값 클래스의 전형적인 예는 String 입니다 . 우리는 equals()를 사용하여 문자열을 비교하고 == 연산자 와 비교할 때 객체가 동일한지 여부는 신경 쓰지 않습니다 . 날짜 및 시간 작업을 위한 대부분의 클래스도 값입니다. 따라서 문서에 명시된 대로 == 연산자를 사용하여 비교하는 것은 나쁜 생각입니다. 더 자세히 알고 싶다면 VALJO에 대한 나의 최근 정의를 확인하세요 . 이 정의는 불변성, 팩토리 메소드, equals () , hashCode , toString() , 그리고 CompareTo .() .
대체 달력
java.time 의 모든 기본 클래스와 마찬가지로 LocalDate     클래스는 ISO-8601 표준 에 설명된 대로 단일 달력에 바인딩됩니다 . 표준 8601은 그레고리력이라고도 알려진 세계 표준 달력을 설명합니다. 표준 연도에는 365일, 윤년 - 366이 포함됩니다. 매 4번째 해는 100으로 나누어지거나 400으로 나누어지지 않는 한 윤년입니다. 계산의 용이성을 위해 새 연도의 첫 해 이전 연도는 0으로 간주됩니다. 이것이 기본 시스템이라는 첫 번째 결과는 결과가 GregorianCalendar를 사용하여 계산된 결과와 항상 일치하지 않는다는 것입니다 . GregorianCalendar 클래스에는 1582년 10월 15일 이전의 모든 날짜에 대해 율리우스력 체계로의 전환이 내장되어 있습니다. 율리우스력 체계에서는 4년마다 예외 없이 윤년이었습니다. 문제는 한 시스템에서 다른 시스템으로의 전환이 역사적 사실인데 왜 java.time이 이를 모델링하지 않는가입니다. 그렇습니다. 여러 나라가 서로 다른 시기에 그레고리력 체계로 전환했기 때문에 바티칸 전환 날짜만 고려하면 대부분의 다른 국가에 대해 잘못된 데이터를 얻을 수 있습니다. 예를 들어, 북미 식민지를 포함한 대영제국은 거의 200년 후인 1752년 9월 14일에 그레고리력으로 전환했습니다. 러시아는 1918년 2월 14일까지 달력을 변경하지 않았으며 스웨덴의 전환은 일반적으로 불분명합니다. 따라서 1918년 이전 날짜의 실제 의미는 상황에 따라 크게 달라집니다. LocalDate 코드 작성자는 불일치를 피하기 위해 율리우스력에서 그레고리력으로의 전환을 전혀 모델링하지 않기로 완전히 합리적인 결정을 내렸습니다. 모든 핵심 클래스에서 ISO-8601을 기본 달력으로 사용하는 두 번째 결과는 나머지 달력을 처리하려면 추가 클래스 세트가 필요하다는 것입니다. 연대기 인터페이스는 대체 달력 작업을 위한 기반으로, 로케일 이름으로 원하는 달력을 찾을 수 있습니다. Java 8 에는 태국 불교 달력, Mingguo(대만 달력), 일본 달력, 이슬람 달력 등 4개의 추가 달력이 함께 제공됩니다 . 다른 달력에는 프로그램이 함께 제공될 수 있습니다. 각 달력에는 ThaiBuddhistDate , MinguoDate , JapaneseDateHijrahDate 와 같은 특별한 날짜 클래스가 있습니다 . 일본 정부와 같이 고도로 지역화된 애플리케이션에 사용하는 것이 합리적입니다. 추가 인터페이스인 ChronoLocalDate는 LocalDate 와 함께 위 4개 클래스의 핵심 추상화로 사용됩니다. , 사용된 달력 유형에 관계없이 코드를 작성할 수 있습니다. 이 추상화가 존재하더라도 사용은 권장되지 않습니다. 이 추상화가 권장되지 않는 이유를 이해하는 것은 전체 java.time API가 작동하는 방식을 이해하는 데 중요합니다 . 결론은 특정 달력을 참조하지 않고 작성된 대부분의 코드가 작동하지 않는 것으로 판명된다는 것입니다. 예를 들어, 1년이 12개월인지 확신할 수 없지만 일부 개발자는 12개월을 추가하여 1년을 모두 추가했다고 생각합니다. 모든 달에 대략 동일한 일수가 포함되어 있는지 확신할 수 없습니다. 콥트 달력에는 30일로 구성된 12개월과 5~6일로 구성된 1개월이 있습니다. 또한, 일본 달력에서는 다음 천황을 포고한 날부터 연도를 계산하기 때문에 다음 해가 현재보다 1이 더 많을 것이라고 확신할 수 없습니다(이 경우 같은 달의 2일까지) 다른 연도에 속할 수 있음). 여러 달력에서 동시에 작동하는 고품질의 작업 코드를 작성하는 유일한 방법은 날짜와 시간에 대한 모든 작업을 수행하는 코드의 핵심을 표준 달력을 사용하고 날짜를 입력/출력할 때만 작성해야 한다는 것입니다. 다른 달력 시스템으로 변환해야 합니까? 즉, 애플리케이션의 저장 및 모든 날짜 조작에 LocalDate를 사용하는 것이 좋습니다. 그리고 입력 및 출력 날짜를 지역화할 때만 일반적으로 사용자 프로필에 저장된 달력 클래스에서 가져오는 ChronoLocalDate 를 사용해야 합니다 . 사실, 대부분의 응용 프로그램에는 그렇게 심각한 현지화가 필요하지 않습니다. 이 장에 설명된 모든 내용에 대해 더 자세한 설명이 필요하면 ChronoLocalDate 클래스 문서를 참조하세요 .      기사 계속 원본 기사     
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION