tl; dr
LocalDate.now( ZoneId.of( "Africa/Tunis" ) )
.atStartOfDay( ZoneId.of( "Africa/Tunis" ) )
.toEpochSecond()
…
LocalDate.now( ZoneId.of( "Africa/Tunis" ) )
.plusDays( 1 )
.atStartOfDay( ZoneId.of( "Africa/Tunis" ) )
.toEpochSecond()
…
"SELECT * FROM orders WHERE placed >= ? AND placed < ? ; "
…
myPreparedStatement.setObject( 1 , start )
myPreparedStatement.setObject( 2 , stop )
java.time
최신 java.time 클래스로 대체되어 현재 레거시가 된 성가신 오래된 날짜 시간 클래스를 사용하고 있습니다.
분명히 당신은 데이터베이스에 정수 유형의 열에 순간을 저장하고 있습니다. 그것은 불행한 일입니다. 대신 SQL-standard와 같은 유형의 열을 사용해야합니다 TIMESTAMP WITH TIME ZONE
. 그러나이 답변을 위해 우리는 우리가 가진 것을 가지고 일할 것입니다.
기록이 밀리 초 단위의 순간을 나타내며 하루 종일 모든 기록을 원하면 시간 범위가 필요합니다. 우리는 시작 순간과 중지 순간이 있어야합니다. 쿼리에는 쌍을 가져야하는 단일 날짜-시간 기준 만 있습니다.
LocalDate
클래스는 시간이 하루의 시간 영역없이없이 날짜 만 값을 나타냅니다.
시간대는 날짜를 결정하는 데 중요합니다. 주어진 순간에 날짜는 지역별로 전 세계적으로 다릅니다. 예를 들어, 파리 에서 자정 이후 몇 분이 지나면 프랑스 는 몬트리올 퀘벡 에서는 여전히 '어제'인 새로운 날 입니다.
시간대가 지정되지 않은 경우 JVM은 현재 기본 시간대를 내재적으로 적용합니다. 이 기본값은 언제든지 변경 될 수 있으므로 결과가 다를 수 있습니다. 원하는 / 예상 시간대를 명시 적으로 인수로 지정하는 것이 좋습니다.
지정 적절한 시간대 이름 의 형식 continent/region
예컨대, America/Montreal
, Africa/Casablanca
, 또는 Pacific/Auckland
. EST
또는 IST
과 같은 3-4 자 약어 는 표준 시간대 가 아니고 , 표준화되지 않았으며, 고유하지도 않은 (!)이므로 사용하지 마십시오.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
JVM의 현재 기본 시간대를 사용하려면 요청하고 인수로 전달하십시오. 생략하면 JVM의 현재 기본값이 암시 적으로 적용됩니다. JVM 내의 모든 앱 스레드에있는 코드에 의해 런타임 중에 언제든지 기본값이 변경 될 수 있으므로 명시 적으로 지정하는 것이 좋습니다.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
또는 날짜를 지정하십시오. 월을 숫자로 설정할 수 있으며 1 월부터 12 월까지 1 ~ 12 번의 정상적인 번호를 지정할 수 있습니다.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
또는 Month
연중 매월 하나씩 미리 정의 된 열거 형 개체를 사용하는 것이 좋습니다 . 팁 : Month
단순한 정수 대신 코드베이스 전체에서 이러한 객체를 사용하여 코드를보다 자체적으로 문서화하고 유효한 값을 보장하며 유형 안전성을 제공하십시오 .
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
A를 LocalDate
손에, 우리는 다음 필요가 순간 하루의 시작과 정지 한 쌍으로 그 변환합니다. 하루가 시간이 00:00:00에 시작된다고 가정하지 마십시오. 일광 절약 시간 (DST)과 같은 예외로 인해 하루가 01:00:00과 같은 다른 시간에 시작될 수 있습니다. 따라서 java.time이 하루의 첫 번째 순간을 결정하도록합니다. 우리는 그러한 이상을 찾기 위해 ZoneId
인수를 전달합니다 LocalDate::atStartOfDay
. 결과는 ZonedDateTime
.
ZonedDateTime zdtStart = ld.atStartOfDay( z ) ;
일반적으로 시간 범위를 정의하는 가장 좋은 방법은 시작은 포함 하고 끝은 배타적 인 Half-Open 접근 방식 입니다 . 따라서 하루는 첫 번째 순간부터 시작하여 다음 날의 첫 번째 순간까지 이어집니다.
ZonedDateTime zdtStop = ld.plusDays( 1 ).atStartOfDay( z ) ; // Determine the following date, and ask for the first moment of that day.
하루 종일 쿼리는 SQL 명령을 사용할 수 없습니다 BETWEEN
. 이 명령은 완전히 닫힘 ( []
) (시작과 끝 모두 포함)이며 반 개방 ( [)
)을 원합니다 . 한 쌍의 기준 >=
과 <
.
열 이름이 잘못되었습니다. 다양한 데이터베이스에서 예약 한 천 단어를 피하십시오. placed
이 예 에서 사용합시다 .
코드는 ?
순간을 지정 하는 자리 표시자를 사용해야합니다 .
String sql = "SELECT * FROM orders WHERE placed >= ? AND placed < ? ; " ;
그러나 우리는 ZonedDateTime
객체를 가지고 있고, 데이터베이스는 위에서 논의한 것처럼 정수를 저장하고 있습니다. 당신이 경우 한 당신의 열을 정의 제대로 우리는 간단하게 전달할 수 ZonedDateTime
나중에 JDBC 4.2을 지원하는 모든 JDBC 드라이버 객체.
그러나 대신에 우리는 전체 초 단위로 epoch로부터 카운트를 얻어야합니다. 나는 당신의 epoch 기준 날짜가 UTC로 1970 년의 첫 번째 순간이라고 가정 할 것입니다. ZonedDateTime
클래스는 나노초 해상도를 지원 하므로 데이터 손실 가능성에주의하십시오 . 분수 초는 다음 줄에서 잘립니다.
long start = zdtStart().toEpochSecond() ; // Transform to a count of whole seconds since 1970-01-01T00:00:00Z.
long stop = zdtStop().toEpochSecond() ;
이제 위에서 정의한 SQL 코드에이 정수를 전달할 준비가되었습니다.
PreparedStatement ps = con.prepareStatement( sql );
ps.setObject( 1 , start ) ;
ps.setObject( 2 , stop ) ;
ResultSet rs = ps.executeQuery();
에서 정수 값을 검색 할 때 객체 (항상 UTC) 또는 객체 (지정된 시간대) ResultSet
로 변환 할 수 있습니다 .Instant
ZonedDateTime
Instant instant = rs.getObject( … , Instant.class ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
java.time 정보
java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 - 시간의 수업을 java.util.Date
, Calendar
, SimpleDateFormat
.
Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.
자세한 내용은 Oracle Tutorial을 참조하십시오 . 그리고 많은 예제와 설명을 위해 Stack Overflow를 검색하십시오. 사양은 JSR 310 입니다.
java.time 클래스는 어디서 구할 수 있습니까?
ThreeTen - 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 java.time에 향후 추가 될 수있는 가능성을 입증하는 곳입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval
, YearWeek
, YearQuarter
, 그리고 더 .