sourcetip

Excel에서 날짜를 나타내는 숫자를 Java Date 객체로 변환

fileupload 2023. 6. 22. 22:08
반응형

Excel에서 날짜를 나타내는 숫자를 Java Date 객체로 변환

Excel에 날짜 열이 있지만 Java 응용 프로그램에서 읽을 때 숫자로 값이 표시됩니다.

Excel 날짜

1/1/2013

로 알고 있습니다.

41275.00

내 자바 애플리케이션에서 숫자를 날짜로 변환하는 방법은 무엇입니까?

다음은 Excel 날짜를 Java 날짜로 변환하는 최소한의 작업 예제입니다.

        Date javaDate= DateUtil.getJavaDate((double) 41275.00);
        System.out.println(new SimpleDateFormat("MM/dd/yyyy").format(javaDate));

어느 쪽이 돌아옵니까?

01/01/2013

다음 패키지도 가져와야 합니다.

java.text.SimpleDateFormat
java.util.Date

tl;dr

최신 java.time 클래스를 사용합니다.

LocalDate                                    // Represent a date-only vaule, without time-of-day and without time zone.
.of( 1899 , Month.DECEMBER , 30 )            // Specify epoch reference date used by *some* versions of Excel. Beware: Some versions use a 1904 epoch reference. Returns a `LocalDate` object.
.plusDays(                                   // Add a number of days. 
    (long) Double.parseDouble( "41275.00" )  // Get a number of whole days from your input string.
)                                            // Returns another instance of a `LocalDate`, per Immutable Objects pattern, rather than altering the original.        
.toString()                                  // Generate text representing the value of this `LocalDate` in standard ISO 8601 format.

2013-01-01

java.time

최신 솔루션은 초기 버전의 Java와 함께 번들된 끔찍한 레거시 날짜-시간 클래스를 대체하는 java.time 클래스를 사용합니다.

에포크 기준일 : 1899-12-30

문서에 따르면 Microsoft Excel의 이 값은 UTC에서 1900-01-01의 epoch 참조 이후의 일 수입니다.내부적으로, 실제 참조 날짜는 이 위키백과 페이지에 문서화된 1899년 12월 30일입니다.

주의하세요, 일부 Excel 버전(macOS의 이전 버전?)은 1904년에 다른 시대를 사용합니다.

코드의 어딘가에 에포크 참조를 설정합니다.

final static public LocalDate EXCEL_EPOCH_REFERENCE = 
    LocalDate.of( 1899 , Month.DECEMBER , 30 )
; // Beware: Some versions of Excel use a 1904 epoch reference.

계산을 해라.

입력 문자열을 다음과 같이 구문 분석합니다.BigDecimal정확성을 위해 (더 빠른 실행을 위해 정확성을 대체하는 부동 소수점 유형을 선택합니다.)

BigDecimal countFromEpoch = new BigDecimal( "41275.00" );

Epoch 참조 날짜에 전체 일 수를 추가합니다.

long days = countFromEpoch.longValue();  // Extract the number of whole days, dropping the fraction.
LocalDate localDate = EXCEL_EPOCH_REFERENCE.plusDays( days );

localDate.toString(): 2013-01-01


java.time 정보

java.time 프레임워크는 Java 8 이상에 내장되어 있습니다.이러한 클래스는 , , 및 와 같은 문제가 있는 오래된 기존 날짜/시간 클래스를 대체합니다.

자세한 내용은 오라클 튜토리얼을 참조하십시오.그리고 스택 오버플로를 검색하여 많은 예와 설명을 찾습니다.사양은 JSR 310입니다.

현재 유지보수 모드에 있는 Joda-Time 프로젝트는 java.time 클래스로 마이그레이션할 것을 권장합니다.

java.time 개체를 데이터베이스와 직접 교환할 수 있습니다.JDBC 4.2 이상을 준수하는 JDBC 드라이버를 사용합니다.문자열이 필요하지 않고, 필요하지 않습니다.java.sql.*반.최대 절전 모드 5 및 JPA 2.2는 java.time을 지원합니다.

java.time 클래스는 어디서 얻습니까?

Apache POI에는 해당 http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DateUtil.html, , 특히 http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DateUtil.html#getJavaDate(double) 에 대한 일부 유틸리티가 있습니다.

참고 Excel 저장소의 날짜는 1900년 이후(경우에 따라 1904년부터일 수 있음)의 일수(소수일 수 포함)입니다.http://support.microsoft.com/kb/180162 을 참조하십시오.

많은 사용자가 이미 지적했듯이 Excel은 날짜와 시간을 1900년 1월 0일 이후의 일 수와 24시간 중 일부를 나타내는 숫자로 저장합니다.ddddd.tttttt.
이를 직렬 날짜 또는 직렬 날짜 시간이라고 합니다.

그러나 여기서의 답변은 기존 라이브러리에서 메소드를 사용할 준비가 되었다는 점을 제외하고 이야기의 일부만 나타냅니다.

Microsoft의 링크된 문서로는 더 이상 명확하지 않습니다.

MS DATEVALUE 함수 상태:

Excel은 계산에 사용할 수 있도록 날짜를 순차적 일련 번호로 저장합니다.기본적으로 1900년 1월 1일은 일련 번호 1이고, 2008년 1월 1일은 1900년 1월 1일 이후 39,447일이기 때문에 일련 번호 39448입니다.

자, 저는 이 진술을 확인할 것입니다.

LocalDate testDate = LocalDate.of(1900, Month.JANUARY, 1).plusDays(39447);
System.out.println(testDate);// prints 2008-01-02

1900년 1월 1일로부터 39,447일 후에 정말로...2008년 1월 2일!

왜 그런 것일까요?

Excel의 날짜가 한 시대(1899년 12월 30일 또는 1900년 1월 1일 또는 1904년...)에서 시작하는 날짜 수로 표시된다는 사실은 이야기의 일부에 불과합니다.

저는 여기서 궁극적인 답을 찾았습니다: Excel의 날짜와 시간(어떤 신이든 누구든 이 사람들을 축복할 수 있습니다.

Excel에서 날짜 루틴을 구현한 개발자들은 Lotus 1-2-3의 동일한 알려진 문제와의 호환성을 위해 의도적으로 버그를 도입했습니다.

그들은 1900년을 윤년으로 취급했지만 그렇지 않습니다. 1900년 1월 28일을 초과하는 날짜는 실제 날짜보다 하루 더 많습니다.

이것이 Excel이 2008년 1월 1일을 39448이라는 숫자로 나타낸다고 생각하는 이유입니다. 1900년 1월 0일 이후 39,448대이기 때문입니다(그렇습니다, Excel은 0으로 생각합니다). 즉 39,447일 + 1900년 1월 29일입니다.

또한 Excel은 직렬 날짜의 날짜 부분을 1904년 1월 0일 이후의 일 수로 처리할 수 있습니다. 이 모드를 1904-모드 또는 1904-시스템이라고 하며 Macintosh 시스템과의 호환성을 위해 사용됩니다.

Excel 날짜는 시간대 정보를 포함하지 않으므로 시간대 정보 없이 /와 LocalDateTime같은 Java 클래스를 사용하는 것이 좋습니다.

글쎄요, 실제로 - 요즘에는 - 1900년 12월 30일부터 시작하는 엑셀 시대를 계산할 수 있지만 그렇지 않습니다.


Excel 데모 - 날짜 형식은 dd/mm/yyyy입니다.

7
날짜가 왼쪽에 숫자로 삽입되었습니다.


필수 변환에 적합한 클래스:

public class SerialDate {

    //days from 1899-12-31 to Instant.EPOCH (1970-01-01T00:00:00Z)
    public static final long EPOCH = -25568L;
    private long serialDays;
    private double serialTime;
    private long epochDays;
    private long daySeconds;

    /**
     * @param date number of Excel-days since <i>January 0, 1899</i>
     */
    public SerialDate(long date) {
        serialDays = date;
        if (date > 59)//Lotus123 bug
            --date;
        epochDays = EPOCH + date;
    }
            
    /**
     * @param date number of days since <i>January 0, 1899</i> with a time fraction
     */
    public SerialDate(double date) {
        this((long)date);
        serialTime = date - serialDays;
        daySeconds = Math.round(serialTime * 24 * 60 * 60);
    }
            
    /**
     * @return days since 1970-01-01
     */
    public long toEpochDays() {
        return epochDays;
    }
            
    /**
     * @return seconds of the day for this SerialDate
     */
    public long toDaySeconds() {
        return daySeconds;
    }
            
    /**
     * @return a value suitable for an Excel date
     */
    public double getSerialDate() {
        return serialTime + serialDays;
    }
    
}

사용 예:

LocalDate dt = LocalDate.ofEpochDay(new SerialDate(41275).toEpochDays());
System.out.println(dt);//prints 2013-01-01

SerialDate sd = new SerialDate(33257.415972222225);
LocalDateTime dt = LocalDateTime.of(
        LocalDate.ofEpochDay(sd.toEpochDays()),
        LocalTime.ofSecondOfDay(sd.toDaySeconds()));
System.out.println(dt);//prints 1991-01-19T09:59

Excel의 일련 날짜는 1900년 1월 1일 이후의 일 수입니다.날짜를 다시 파악하기 위해서는 일련번호를 일 단위로 추가해야 합니다.

종속성이 없는 Java 8용

```

  /*

    1900-1-0            0
    1900-1-1            1
    1900-1-2            2
    1900-1-3            3


     */


    int days = 43323;
    LocalDate start = LocalDate.of(1900, 1, 1);
    LocalDate today = LocalDate.of(2018, 8, 11);


    // days to date
    LocalDate date = start.plusDays(days).minusDays(2);

    System.out.println(date);

    // date to days
    long days1 = ChronoUnit.DAYS.between(start, today) + 2;
    System.out.println(days1);

```

LocalDateTime의 SerialDate 클래스 예제에 따라 다음 코드를 사용했습니다.

// somewhere as double static 
LocalDateTime EXCEL_START = LocalDateTime.of(1899, 12, 30, 0, 0);
Double doubleValue = 44705.416666666664; // input

long days = doubleValue.longValue();
long seconds = Math.round((doubleValue - days) * 24 * 60 * 60);
LocalDateTime converted = EXCEL_START
            .plusDays(days)
            .plusSeconds(seconds); //2022-05-24T10:00

언급URL : https://stackoverflow.com/questions/19028192/converting-number-representing-a-date-in-excel-to-a-java-date-object

반응형