Truncating java.util.Date to LocalDate *without* toInstant() because java.sql.Date gives UnsupportedOperationException
如果我在一个恰好是
1 2 3 4 5 6 | try { java.util.Date input = new java.sql.Date(System.currentTimeMillis()); LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); } catch (UnsupportedOperationException e) { // grrr! } |
我关心的
现在以下相关问题都非常有趣:
UnsupportedOperationException - 为什么不能在java.sql.Date上调用onInstant()?
将java.util.Date转换为java.time.LocalDate
LocalDate到java.util.Date,反之亦然最简单的转换?
但它们没有提供任何优雅的方法来截断
我承认存在一个问题,即一个时区中的同一时刻可能与另一个时区的同一时刻不同。
我怀疑解决方案将涉及java.util.Calendar,而不是制定我自己的解决方案,我宁愿建立别人先做的事情。
我宁愿找到比这更短的东西:
from Resetting the time part of a timestamp in Java :
1
2
3
4
5
6
7
8 Date date = new Date(); // timestamp now
Calendar cal = Calendar.getInstance(); // get calendar instance
cal.setTime(date); // set cal to date
cal.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight
cal.set(Calendar.MINUTE, 0); // set minute in hour
cal.set(Calendar.SECOND, 0); // set second in minute
cal.set(Calendar.MILLISECOND, 0); // set millis in second
Date zeroedDate = cal.getTime(); // actually computes the new Date
通常最简单的解决方案是最难找到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public LocalDate convertDateObject(java.util.Date suspectDate) { try { // Don't do this if there is the smallest chance // it could be a java.sql.Date! return suspectDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); } catch (UnsupportedOperationException e) { // BOOM!! } // do this first: java.util.Date safeDate = new Date(suspectDate.getTime()); return safeDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); } |
如果
1 |
不幸的是,你不能在
如果你不知道类型(它可以是
1 2 3 4 5 6 7 | LocalDate date = Instant // get the millis value to build the Instant .ofEpochMilli(input.getTime()) // convert to JVM default timezone .atZone(ZoneId.systemDefault()) // convert to LocalDate .toLocalDate(); |
但是,如果您确实要将时间设置为午夜,则可以使用
1 2 3 4 5 6 7 8 9 | LocalDate date = Instant // get the millis value to build the Instant .ofEpochMilli(input.getTime()) // convert to JVM default timezone .atZone(ZoneId.systemDefault()) // set time to midnight .with(LocalTime.MIDNIGHT) // convert to LocalDate .toLocalDate(); |
但正如我所说,
您还可以检查日期的类型并相应地选择相应的操作,如下所示:
1 2 3 4 5 |
您可以根据需要使用任何其他时区,而不是使用JVM默认时区(
避免使用3个字母的缩写(如
您可以通过调用
TL;博士
1 | myResultSet.getObject( … , LocalDate.class ) |
java.time
使用遗留日期时间类(例如
您说该值在
使用符合JDBC 4.2或更高版本的JDBC驱动程序,使用java.time类与数据库交换值。
1 | LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ; |
然后转到
1 | myPstmt.setObject( … , myLocalDate ) ; |
试试这个。
1 2 3 |
TL;博士
你在
If I use java.util.Date … on a variable which happens to be a java.sql.Date
您违反了课程文件中规定的合同。你被告知要忽略
但解决方案可能非常简单。
1 | ZonedDateTime zdt = myJavaSqlDate.toLocalDate().atStartOfDay( ZoneId.of("America/Montreal" ) ) ; |
细节
显然你手头有
两个
遇到遗留日期时间对象时的第一步:使用添加到旧类的新方法转换为java.time。
将我们的假日期对象
1 | LocalDate ld = myJavaSqlDate.toLocalDate() ; |
显然,您希望将该仅限日期的值转换为具有一天中的时间的日期。也许你想要一天的第一时刻。确定第一个时刻需要一个时区。例如,新的一天早于
1 2 | ZoneId z = ZoneId.of("Pacific/Auckland" ) ; ZonedDateTime zdt = ld.atStartOfDay( z ) ; |
您是否尝试使用SimpleDateFormat来帮助您?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.ZoneId; import java.util.Date; public class Utils { private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd" ); public static void main( String[] args ) { LocalDate ld = sqlDateToLocalDate( new java.sql.Date( System.currentTimeMillis() ) ); System.out.println( ld ); } public static LocalDate sqlDateToLocalDate( java.sql.Date sqlDate ) { try { Date d = sdf.parse( sdf.format( sqlDate ) ); return d.toInstant().atZone( ZoneId.systemDefault() ).toLocalDate(); } catch ( ParseException exc ) { } return null; } } |