CodeGym /Java Blog /무작위의 /시간을 잃지 않는 방법: DateTime 및 Calendar
John Squirrels
레벨 41
San Francisco

시간을 잃지 않는 방법: DateTime 및 Calendar

무작위의 그룹에 게시되었습니다
안녕! 오늘 우리는 이전에 본 적이 없는 새로운 데이터 유형, 즉 날짜로 작업을 시작할 것입니다. 시간을 잃지 않는 방법: DateTime 및 Calendar - 1데이트가 무엇인지 설명할 필요는 없을 것 같습니다. :) 원칙적으로 현재 날짜와 시간을 일반 Java String에 저장할 수 있습니다.

public class Main {
   public static void main(String[] args) {

       String date = "June 11, 2018";
       System.out.println(date);
   }
}
그러나 이 방법에는 많은 단점이 있습니다. 이 String클래스는 텍스트 작업을 위해 설계되었으며 해당 메서드는 이 작업에 적합합니다. 어떤 식으로든 날짜를 조작해야 하는 경우(예: 2시간 추가)는 String잘 작동하지 않습니다. 또는 프로그램이 컴파일될 때 현재 날짜와 시간을 표시하려는 경우. String여기서도 도움이 되지 않습니다. 코드를 작성하고 실행할 때쯤에는 시간이 변경되고 콘솔에 잘못된 정보가 표시됩니다. 이것이 바로 Java 제작자가 날짜 및 시간 작업을 위한 여러 클래스를 제공한 이유입니다. 그 중 첫 번째는java.util.Date

데이트 클래스

다른 Java 패키지에 클래스가 있으므로 전체 이름을 지정했습니다 java.sql.Date. 혼동하지 마십시오! 그것에 대해 알아야 할 첫 번째 사항은 1970년 1월 1일 이후 경과된 밀리초 수로 날짜를 저장한다는 것입니다. 이 시간 시스템에는 " Unix-time "이라는 자체 이름도 있습니다. 당신은 동의합니까? :) 기억할 가치가 있는 두 번째 사항은 다음과 같습니다. 기본 생성자를 사용하여 객체를 생성하면 Date결과는 객체가 생성된 순간의 현재 날짜와 시간을 나타냅니다 . 로 표시된 날짜는 String이러한 작업에 어려움을 겪을 것이라고 말한 것을 기억하십니까? 클래스 Date는 쉽게 처리합니다.

public class Main {
   public static void main(String[] args) {

       Date date = new Date();
       System.out.println(date);
   }
}
이 코드를 여러 번 실행하면 시간이 반복적으로 변경되는 것을 볼 수 있습니다. :) 이것은 시간이 밀리초로 저장되기 때문에 가능합니다. 밀리초는 매우 작은 시간 단위이므로 결과가 매우 정확합니다. 다른 생성자 클래스 Date: 1970년 1월 1일 00:00부터 필요한 날짜까지 정확한 밀리초 수를 전달할 수 있으며 해당 날짜 개체가 생성됩니다.

public class Main {
   public static void main(String[] args) {

       Date date = new Date(1212121212121L);
       System.out.println(date);
   }
}
콘솔 출력: Fri May 30 04:20:12 GMT 2008 우리는 2008년 5월 30일을 얻습니다. "Fri"는 요일(금요일)을 나타내고 GMT는 시간대(그리니치 표준시)를 나타냅니다. long밀리초는 일반적으로 에 맞지 않기 때문에 밀리초는 s 로 전달됩니다 int. 그렇다면 수행해야 할 날짜가 있는 작업은 무엇입니까? 물론 가장 분명한 것은 비교 입니다 . 특정 날짜가 다른 날짜보다 앞설지 뒤날지 결정하기 위해. 이는 여러 가지 방법으로 수행할 수 있습니다. 예를 들어, Date.getTime()1970년 1월 1일 자정 이후 경과된 시간(밀리초)을 반환하는 메서드를 호출할 수 있습니다. 두 개의 Date 개체에 대해 호출하고 결과를 비교하면 됩니다.

public class Main {
   public static void main(String[] args) {

       Date date1 = new Date();

       Date date2 = new Date();

       System.out.println((date1.getTime() > date2.getTime())?
               "date1 is later than date2" : "date1 is earlier than date2");
   }
}
출력: date1은 date2보다 이전입니다. 그러나 더 편리한 방법도 있습니다. 즉, Date 클래스에서 제공하는 특수 메서드인 before(), after()및 를 사용하는 것입니다 equals(). 모두 부울 값을 반환합니다. 이 before()메서드는 날짜가 인수로 전달된 날짜보다 이전인지 확인합니다.

public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);// Suspend the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.before(date2));
   }
}
콘솔 출력: true 마찬가지로 after()메서드는 날짜가 인수로 전달된 날짜보다 이후인지 확인합니다.

public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);// Suspend the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.after(date2));
   }
}
콘솔 출력: false 이 예제에서는 2초 동안 "프로그램을 절전 모드로 전환"하여 두 날짜가 서로 다르다는 것을 보장합니다. date1빠른 컴퓨터에서는 및 생성 사이의 시간이 date21밀리초 미만일 수 있으므로 둘 다 before()false after()를 반환합니다. 하지만 이 경우 equals()메서드는 true를 반환합니다! 결국 각 날짜에 대해 1970년 1월 1일 00:00 이후의 밀리초 수를 비교합니다 . 객체는 밀리초와 일치하는 경우에만 동일한 것으로 간주됩니다 .

public static void main(String[] args) {

   Date date1 = new Date();
   Date date2 = new Date();

   System.out.println(date1.getTime());
   System.out.println(date2.getTime());

   System.out.println(date1.equals(date2));
}
여기서 주의해야 할 또 다른 사항이 있습니다. OracleDate 웹 사이트 에서 해당 클래스 에 대한 문서를 열면 많은 메서드와 생성자가 Deprecated (즉, 사용하지 않는 것이 좋습니다) 로 표시되어 있음을 알 수 있습니다 . 다음은 더 이상 사용되지 않는 클래스의 일부에 대해 Java 제작자가 말한 내용입니다.
"@Deprecated 주석이 달린 프로그램 요소는 일반적으로 위험하거나 더 나은 대안이 있기 때문에 프로그래머가 사용하지 않는 것이 좋습니다."
그렇다고 이러한 방법을 전혀 사용할 수 없다는 의미는 아닙니다. IDE에서 사용되지 않는 메서드를 사용하여 코드를 실행하려고 하면 대부분 작동할 것입니다. 예를 들어 개체 Date.getHours()와 연결된 시간을 반환하는 사용되지 않는 메서드를 고려하십시오 Date.

public static void main(String[] args) {

   Date date1 = new Date();

   System.out.println(date1.getHours());
}
14:21(오후 2:21)에 코드를 시작하면 숫자 14가 표시됩니다. 보시다시피 더 이상 사용되지 않는 메서드에 줄이 그어져 있지만 여전히 작동합니다. 이러한 메서드는 이를 사용하는 기존 코드의 거대한 본문을 중단하지 않기 위해 제거되지 않습니다. 즉, 이러한 메서드는 "손상"되거나 "제거"되지 않습니다. 더 편리한 대안을 사용할 수 있기 때문에 사용을 권장하지 않습니다. 부수적으로 문서에는 이 대안이 구체적으로 언급되어 있습니다.
시간을 잃지 않는 방법: DateTime 및 Calendar - 2
대부분의 Date클래스 메서드는 개선되고 확장된 클래스로 이동되었습니다 Calendar. 다음에 그 클래스에 대해 알게 될 것입니다. :)

캘린더 클래스

JDK 1.1에서는 새로운 클래스인 Calendar. 이전보다 Java에서 날짜 작업이 다소 쉬워졌습니다. Calendar우리가 작업할 클래스의 유일한 구현은 GregorianCalendar클래스입니다. 그것은 세계 대부분의 국가에서 관찰되는 그레고리력을 구현합니다. 가장 큰 장점은 더 편리한 형식으로 날짜를 사용할 수 있다는 것입니다. 예를 들어 다음을 수행할 수 있습니다.
  • 현재 날짜에 월 또는 일 추가
  • 연도가 윤년인지 확인하십시오.
  • 날짜의 개별 구성 요소를 반환합니다(예: 전체 날짜에서 월 번호 추출).
  • 그것은 또한 매우 편리한 상수 체계를 포함하고 있습니다.
이 클래스의 또 다른 중요한 개선 사항은 Calendar.ERACalendar 상수 입니다 . 일반 시대 이전(BC - 그리스도 이전) 또는 일반 시대(AD - Anno Domini)의 날짜를 표시할 수 있습니다. 예를 들어 이 모든 것을 살펴보겠습니다. 날짜가 2017년 1월 25일인 객체를 생성해 보겠습니다 .calendar

public static void main(String[] args) {

  Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
Calendar클래스(그 문제에 대한 클래스와 마찬가지로 Date) 에서 월은 0부터 시작하므로 숫자 0을 두 번째 인수로 전달합니다. 학급 과 함께 작업할 때 Calendar이것이 개별 날짜가 아니라 단지 달력 이라는 점을 이해하는 것이 중요합니다 . 시간을 잃지 않는 방법: DateTime 및 Calendar - 3 날짜는 특정 시간 간격을 나타내는 몇 개의 숫자입니다. 달력은 날짜로 많은 일을 할 수 있는 전체 시스템입니다. :) 개체를 표시하려고 하면 다음과 같이 명확하게 알 수 있습니다 Calendar. 출력: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="유럽/런던",offset=0,dstSavings=0,useDaylight= false,transitions=79,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=0,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=25,DAY_OF_YEAR=?,DAY_OF_WEEK=? ,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?] 얼마나 많은 정보를 얻었는지 확인하세요! 달력에는 일반 날짜에는 없는 많은 속성이 있으며 모두 표시됩니다(toString()에서 메서드가 작동하는 방식Calendar). Date달력에서 간단한 날짜(예: 개체)를 가져와야 하는 경우Calendar.getTime()방법(이름이 가장 논리적이지는 않지만 무엇을 할 수 있습니까?):

public static void main(String[] args) {

   Calendar calendar = new GregorianCalendar(2017, 0 , 25);
   Date date = calendar.getTime();
   System.out.println(date);
}
출력: Wed Jan 25 00:00:00 GMT 2017 이제 우리는 달력을 가져와 일반적인 날짜로 "축소"했습니다. 더 가자. 숫자로 월을 지정하는 것 외에도 Calendar클래스의 상수 필드 값을 사용할 수 있습니다 . Calendar이러한 상수는 변경할 수 없는 사전 설정 값이 있는 클래스 의 정적 필드입니다 . 이 옵션을 사용하면 코드의 가독성이 향상되므로 실제로 더 나은 옵션입니다.

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY 는 월을 나타내는 상수 중 하나입니다. 이러한 명명된 상수를 사용하면 예를 들어 숫자 3이 우리가 3월이라고 부르는 세 번째 달이 아니라 4월을 의미한다는 사실을 잊지 못할 것입니다. Calendar.APRIL 을 작성하면완료됩니다. :) 모든 달력 필드(숫자, 월, 분, 초 등)는 메서드를 사용하여 별도로 지정할 수 있습니다set(). 이 방법은Calendar클래스에 각 필드에 대한 상수가 있고 결과 코드를 읽기가 매우 쉽기 때문에 매우 편리합니다. 마지막 예에서는 날짜를 만들었지만 시간은 설정하지 않았습니다. 시간을 맞추자 19:42:12

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar();
   calendar.set(Calendar.YEAR, 2017);
   calendar.set(Calendar.MONTH, 0);
   calendar.set(Calendar.DAY_OF_MONTH, 25);
   calendar.set(Calendar.HOUR_OF_DAY, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println(calendar.getTime());
}
출력: Wed Jan 25 19:42:12 GMT 2017 메서드를 호출하여 set()상수(변경하려는 필드에 따라 다름)와 필드의 새 값을 전달합니다. set()이 방법은 하나의 필드뿐만 아니라 많은 필드에 대해 값을 설정하는 방법을 알고 있는 일종의 "슈퍼 세터"인 것으로 밝혀졌습니다 . :) 클래스는 값을 더하고 빼는 메서드를 Calendar사용합니다 . add()변경하려는 필드와 숫자(현재 값에서 정확히 얼마나 더하거나 빼려는지)를 전달합니다. 예를 들어 생성한 날짜보다 2개월 전 날짜를 가져옵니다.

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.add(Calendar.MONTH, -2); // To subtract, pass a negative number
   System.out.println(calendar.getTime());
}
출력: 2016년 11월 25일 금요일 19:42:12 GMT 매우 좋습니다! 2개월 전에 날짜를 잡았습니다. 이로 인해 월이 변경되었을 뿐만 아니라 연도도 2017년에서 2016년으로 변경되었습니다. 물론 날짜를 변환할 때 현재 연도는 수동으로 추적할 필요 없이 자동으로 계산됩니다. 그러나 어떤 이유로 이 동작을 비활성화해야 하는 경우 그렇게 할 수 있습니다. 이 메서드는 나머지 값에 영향을 주지 않고roll() 값을 더하거나 뺄 수 있습니다 . 예를 들면 다음과 같습니다.

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(calendar.getTime());
}
이전 예에서와 똑같은 작업을 수행했습니다. 현재 날짜에서 2개월이 걸렸습니다. 그러나 이제 코드는 다른 작업을 수행합니다. 월은 1월에서 11월로 변경되었지만 연도는 변경되지 않았습니다. 바로 2017입니다! 출력: 2017년 11월 25일 토요일 10:42:12 GMT 위에서 말했듯이 모든 Calendar필드를 별도로 가져올 수 있습니다. 다음과 같은 방법 으로 이를 수행합니다 get().

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println("Year: " + calendar.get(Calendar.YEAR));
   System.out.println("Month: " + calendar.get(Calendar.MONTH));
   System.out.println("Week in the month: " + calendar.get(Calendar.WEEK_OF_MONTH));// Week in this month?

   System.out.println("Day: " + calendar.get(Calendar.DAY_OF_MONTH));

   System.out.println("Hours: " + calendar.get(Calendar.HOUR));
   System.out.println("Minutes: " + calendar.get(Calendar.MINUTE));
   System.out.println("Seconds: " + calendar.get(Calendar.SECOND));
   System.out.println("Milliseconds: " + calendar.get(Calendar.MILLISECOND));

}
출력: 연도: 2017 년 월: 0 주: 5일: 25시간: 10분: 42초: 12밀리초:Calendar 0 ". :) 물론, 이 클래스의 또 다른 흥미로운 측면은 시대를 다루는 것입니다. "BC" 날짜를 만들려면 Calendar.ERA 필드를 사용해야 합니다. 예를 들어 Hannibal이 로마 군대를 격파한 Cannae 전투의 날짜를 만들어 보겠습니다. 이것은 기원전 216년 8월 2일에 일어났습니다.

public static void main(String[] args) {
   GregorianCalendar cannae = new GregorianCalendar(216, Calendar.AUGUST, 2);
   cannae.set(Calendar.ERA, GregorianCalendar.BC);

   DateFormat df = new SimpleDateFormat("MMM dd, yyy GG");
   System.out.println(df.format(cannae.getTime()));
}
여기에서 클래스를 사용하여 SimpleDateFormat이해하기 쉬운 형식으로 날짜를 인쇄했습니다(문자 "GG"는 연호를 표시해야 함을 나타냄). 산출: 기원전 216년 8월 2일. Calendar클래스에는 더 많은 메서드와 상수가 있습니다. 문서 에서 이에 대해 읽을 수 있습니다 . 이 날짜 형식이 마음에 들지 않으면 2017년 11월 25일 토요일 10:42:12 GMT를SimpleDateFormat 사용하여 원하는 대로 쉽게 만들 수 있습니다.

public static void main(String[] args) {

   SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM d, yyyy");
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(dateFormat.format(calendar.getTime()));
}
출력: 2017년 11월 25일 토요일 훨씬 낫지 않나요? :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION