将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp
Posted
技术标签:
【中文标题】将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp【英文标题】:Convert LocalDate to LocalDateTime or java.sql.Timestamp 【发布时间】:2012-02-18 00:30:46 【问题描述】:我正在使用 JodaTime 1.6.2。
我有一个 LocalDate
,我需要将其转换为 (Joda) LocalDateTime
或 java.sqlTimestamp
以进行映射。
原因是我已经弄清楚如何在 LocalDateTime
和 java.sql.Timestamp
之间进行转换:
LocalDateTime ldt = new LocalDateTime();
DateTimeFormatter dtf = DateTimeFormatter.forPattern("yyyy-MM-dd HH:mm:ss");
Timestamp ts = Timestamp.valueOf(ldt.toString(dtf));
所以,如果我可以在LocalDate
和LocalDateTime
之间进行转换,那么我可以继续转换为java.sql.Timestamp
。感谢您在正确方向上的任何推动!
【问题讨论】:
仅供参考,Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。见Tutorial by Oracle。此外,java.sql.Timestamp
类现在是遗留的,被 java.time 类取代,特别是被Instant
。
【参考方案1】:
乔达时间
要将 JodaTime 的 org.joda.time.LocalDate
转换为 java.sql.Timestamp
,只需这样做
Timestamp timestamp = new Timestamp(localDate.toDateTimeAtStartOfDay().getMillis());
要将 JodaTime 的 org.joda.time.LocalDateTime
转换为 java.sql.Timestamp
,只需这样做
Timestamp timestamp = new Timestamp(localDateTime.toDateTime().getMillis());
Java时间
要将 Java8 的 java.time.LocalDate
转换为 java.sql.Timestamp
,只需这样做
Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay());
要将 Java8 的 java.time.LocalDateTime
转换为 java.sql.Timestamp
,只需这样做
Timestamp timestamp = Timestamp.valueOf(localDateTime);
【讨论】:
在将LocalDateTime
转换为DateTime
时要小心,因为并非所有LocalDateTime
s 都是有效的DateTime
s。来源:joda-time.sourceforge.net/faq.html#illegalinstant 刚刚碰到这个。
在 valueOf() 接受字符串时出现参数编译错误。
@Patriotic:只有在您实际上没有使用 Java SE 1.8 或更高版本时才会发生这种情况。如答案和提供的 Javadoc 链接中所示(上面答案中的蓝色文本实际上是链接,您可以单击它们以深入了解 Javadoc),Timestamp#valueOf()
方法自 Java SE 1.8 起接受 @987654347 @.
java.lang.IllegalArgumentException: 时间戳格式必须是 yyyy-mm-dd hh:mm:ss[.fffffffff];;;;我做Timestamp.valueOf(Timestamp(longtimestampppp).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().toString())
只要按照答案中的最后一个示例,而不是无缘无故地对其进行toString()
。【参考方案2】:
使用 Java 8 time API 的最佳方式:
LocalDateTime ldt = timeStamp.toLocalDateTime();
Timestamp ts = Timestamp.valueOf(ldt);
用于与您的模型一起放入的 JPA (https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa):
@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp>
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime ldt)
return Timestamp.valueOf(ldt);
@Override
public LocalDateTime convertToEntityAttribute(Timestamp ts)
return ts.toLocalDateTime();
所以现在是相对时区独立时间。 此外,它很容易做到:
LocalDate ld = ldt.toLocalDate();
LocalTime lt = ldt.toLocalTime();
格式:
DateTimeFormatter DATE_TME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
String str = ldt.format(DATE_TME_FORMATTER);
ldt = LocalDateTime.parse(str, DATE_TME_FORMATTER);
更新:postgres 9.4.1208、HSQLDB 2.4.0 等无需任何对话即可理解 Java 8 Time API!
【讨论】:
有人可以帮我解决这个问题吗?它不工作***.com/questions/69533213/…@BalusC【参考方案3】:tl;博士
Joda-Time 项目处于维护模式,现在被 java.time 类取代。
只需使用java.time.Instant
类。
不需要:
LocalDateTime
java.sql.Timestamp
字符串
以 UTC 捕获当前时刻。
Instant.now()
将该时刻存储在数据库中:
myPreparedStatement.setObject( … , Instant.now() ) // Writes an `Instant` to database.
从数据库中检索那个时刻:
myResultSet.getObject( … , Instant.class ) // Instantiates a `Instant`
将挂钟时间调整为特定时区的时间。
instant.atZone( z ) // Instantiates a `ZonedDateTime`
LocalDateTime
是错误的类
其他答案是正确的,但他们没有指出 LocalDateTime
是错误的类。
在 java.time 和 Joda-Time 中,LocalDateTime
故意缺少任何时区或与 UTC 偏移的概念。因此,它确实不代表一个时刻,并且不是时间线上的一个点。 LocalDateTime
代表关于大约 26-27 小时范围内潜在时刻的粗略概念。
当区域/偏移量未知(不是很好的情况)或区域偏移量不确定时,使用LocalDateTime
。例如,“圣诞节从 2018 年 12 月 25 日的第一刻开始”将表示为 LocalDateTime
。
使用ZonedDateTime
表示特定时区的某个时刻。例如,在Pacific/Auckland
或America/Montreal
等任何特定区域开始的圣诞节将用ZonedDateTime
对象表示。
暂时始终使用 UTC,请使用 Instant
。
Instant instant = Instant.now() ; // Capture the current moment in UTC.
应用时区。同一时刻,时间轴上的同一点,但以不同的挂钟时间查看。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, different wall-clock time.
所以,如果我可以在 LocalDate 和 LocalDateTime 之间进行转换,
不,错误的策略。如果您有仅日期值,并且需要日期时间值,则必须指定时间。对于特定区域,该时间可能在该日期无效 - 在这种情况下,ZonedDateTime
类会根据需要自动调整时间。
LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 14 , 0 ) ; // 14:00 = 2 PM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
如果您想将一天中的第一个时刻作为您的时间,让 java.time 确定那个时刻。不要假设一天从 00:00:00 开始。夏令时 (DST) 等异常情况意味着一天可能从另一个时间开始,例如 01:00:00。
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
java.sql.Timestamp
是错误的类
java.sql.Timestamp
是麻烦的旧日期时间类的一部分,这些类现在已经遗留,完全被 java.time 类所取代。该类用于表示UTC 中的一个时刻,分辨率为nanoseconds。现在,java.time.Instant
可以实现这一目的。
JDBC 4.2 与 getObject
/setObject
从JDBC 4.2 及以后,您的JDBC driver 可以通过调用直接与数据库交换java.time 对象:
PreparedStatement::setObject
ResultSet::getObject
例如:
myPreparedStatement.setObject( … , instant ) ;
……和……
Instant instant = myResultSet.getObject( … , Instant.class ) ;
转换传统 ⬌ 现代
如果您必须与尚未更新到 java.time 的旧代码交互,请使用添加到旧类的新方法来回转换。
Instant instant = myJavaSqlTimestamp.toInstant() ; // Going from legacy class to modern class.
……和……
java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( instant ) ; // Going from modern class to legacy class.
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.*
类。
从哪里获得 java.time 类?
Java SE 8、Java SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 Java SE 7 大部分 java.time 功能都在ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和more。
【讨论】:
【参考方案4】:根据您的时区,您可能会损失几分钟(1650-01-01 00:00:00 变为 1649-12-31 23:52:58)
使用下面的代码来避免这种情况
new Timestamp(localDateTime.getYear() - 1900, localDateTime.getMonthOfYear() - 1, localDateTime.getDayOfMonth(), localDateTime.getHourOfDay(), localDateTime.getMinuteOfHour(), localDateTime.getSecondOfMinute(), fractional);
【讨论】:
【参考方案5】:对java.time.LocalDate
对象的函数调用asStartOfDay()
返回一个java.time.LocalDateTime
对象
【讨论】:
【参考方案6】:由于 Joda 逐渐消失,有人可能希望在 Java 8 中将 LocaltDate
转换为 LocalDateTime
。在 Java 8 中,LocalDateTime
将提供一种使用 LocalDate
和 @ 创建 LocalDateTime
实例的方法987654330@。检查here.
public static LocalDateTime of(LocalDate date, 本地时间)
示例是,
// just to create a sample LocalDate
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf);
// convert ld into a LocalDateTime
// We need to specify the LocalTime component here as well, it can be any accepted value
LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00
仅供参考,获取下面的纪元秒数可以使用,
ZoneId zoneId = ZoneId.systemDefault();
long epoch = ldt.atZone(zoneId).toEpochSecond();
// If you only care about UTC
long epochUTC = ldt.toEpochSecond(ZoneOffset.UTC);
【讨论】:
这里根本不需要使用LocalDateTime
。该类故意缺少任何时区或与 UTC 偏移的概念。所以它在这里没有用处。相反:LocalDate.parse( “20180306” , DateTimeFormatter.BASIC_ISO_DATE ).atStartOfDay( ZoneId.of( “Africa/Tunis” ).toEpochSecond()
不要假设一天从 00:00 开始,并非总是如此。
你的意思是什么不要假设一天从 00.00 开始
Daylight Saving Time (DST) 等异常意味着在某些地方的某些日期,一天可能从另一个时间开始,例如 01:00:00。因此,与其假设,不如让 java.time 通过调用java.time.LocalDate.atStartOfDay
来确定第一个时刻以获取ZonedDateTime
。请参阅my Answer 中的示例。正如我所评论的那样,LocalDateTime
类在这一切中都是无用的并且适得其反。
所以对于LocalDateTime
,我们必须使用ZoneId
?
我认为你错过了我的所有观点。在此页面上重新阅读我的答案。搜索 Stack Overflow 以从更多示例和讨论中了解更多信息。但我会在这里最后一次说:LocalDateTime
不 适合手头的问题。 LocalDateTime
确实不代表片刻。 LocalDateTime
与任何特定的地区或时区无关,尽管名称乍一看可能暗示其他含义 - 了解有关本课程的意图和详细信息的更多信息。 LocalDateTime
类确实有目的,但不是本问题中看到的目的。【参考方案7】:
Java8 +
import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)
【讨论】:
有用,但似乎并不能真正回答问题。 感谢代码,但与问题无关。以上是关于将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Joda Localdate 转换为 Joda DateTime?
将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp
如何将 Javascript 日期转换为 Spring @RequestParam 的 LocalDate?
如何在不使用 DateTimeFormatter 的情况下将字符串转换为 LocalDate [重复]
将通过 JDBC 检索到的 java.sql.Date 值转换为 java.time.LocalDate? [复制]
Spring Data - 如何将 YearMonth 类型的 @Param 转换为 LocalDate 的开始和结束?