tl;博士
LocalDateTime.of( // A `LocalDateTime` represents a set of *potential* moments along a range of about 26-27 hours. Not an actual moment, not a point on the timeline.
LocalDate.systemDefault() , // Get the JVMâs current default time zone. Can change at any moment *during* runtime. When crucial, always confirm with the user.
LocalTime.parse( "14:57" ) // Parse a string in standard ISO 8601 format as a time-of-day without regard for time zone or offset-from-UTC.
) // Returns a `LocalDateTime` object.
.atZone( // Determine an actual moment, a point on the timeline.
ZoneId( "Africa/Tunis" ) // Specify a time zone as `Continent/Region`, never as 3-4 letter pseudo-zones such as `PST`, `CST`, or `IST`.
) // Returns a `ZonedDateTime` object.
.toInstant() // Extracts a `Instant` object from the `ZonedDateTime` object, always in UTC by default.
详细信息
目前有点混乱
日期时间处理为
非常
令人困惑的工作。
提示:
-
忘记你自己的时区吧。从以下方面考虑
UTC
而不是你自己的狭隘时区。
-
了解真实时刻(时间轴上的点)和日期时间近似值之间的差异
不
在时间轴上,通常称为“本地”值。
-
阅读堆栈溢出或internet上其他位置有关日期时间的信息时要小心。你会遇到糟糕的建议和许多错误的解决方案。
拥有所有的选择;时间戳、日期、本地时间等。
永远不要使用与Java最早版本捆绑在一起的麻烦的旧遗留日期时间类。从不使用
java.sql.Timestamp
,则,
java.util.Date
,则,
java.util.Calendar
等等
仅使用中的类
java.time
package
。
这个
JAVA时间
课程是业界领先的日期-时间框架。经过精心设计和深思熟虑,从
Joda-Time
项目成功。
有人知道如何做到这一点,或者可以提供一些提示/最佳做法吗?
你可能会后悔你的要求。继续读下去。
目前,我得到了一个带有日期数据类型的“航班”类;出发和到达日期时间。
因此,请定义
Flight
班
在现实生活中,飞行在未来发生的距离足够远,以至于我们冒着政客改变时区定义的风险。最常见的变化是采用/删除/更改
Daylight Saving Time (DST)
.但由于各种原因,会定期进行任意更改。我们可以对这种变化的明智性/理智性进行辩论,但事实是它们确实发生了。这种情况经常发生,因为政客们似乎奇怪地倾向于在世界各地的许多国家做出这些改变。几乎所有人都是在几乎没有预警的情况下这样做的,有时只是几周。甚至没有任何警告
North Korea did this week
。
我有
不
了解航空公司实际上是如何工作的,但通过浏览航空公司的时间表和各种读数,他们似乎试图利用出发地点的分区时间来维持他们的时间表。因此,如果航班计划在上午6点起飞,他们会在DST转换的前一天、第二天和第二天保留该航班时间表。如果这确实是一般意图,那就意味着在一个DST切换上无所事事地消磨时间,同时在另一个DST切换上努力节省一个小时。显然地
Amtrak adopts this practice
为了它的火车。让我们继续这个方法。
使用这种假想的时间表方法意味着我们无法确定未来早上6点的确切时间。因此,我们需要记录我们对那个日期和一天中的那个时间的渴望,而不应用时区。但我们必须记录下所需的时区,以便我们知道在什么情况下,我们可以稍后确定确切的时刻,何时足够接近,我们不必担心时区的变化。
所以我们使用
LocalDate
和
LocalTime
类型,因为它们故意缺乏
time zone
(中的名称
Continent/Region
格式)或
offset-from-UTC
(小时分秒数)。
这个
ZoneId
类表示时区。
我在用这个词
Unzoned
以提醒我们这些值
不
表示时间线上的实际时刻。“本地”这个词往往会让初学者感到困惑。
public class Flight {
private String flightNumber;
private LocalDate departureDateUnzoned;
private LocalTime departureTimeUnzoned;
private ZoneId departureZoneId ;
}
对于到达,存储该航班的预期时间跨度,而不是到达日期时间。您可以计算到达时间,因此无需存储它。这个
Duration
类跟踪小时、分钟、秒和分数秒的数量。
要计算到达时间,让我们使用
LocalDateTime
类,它只是将
本地日期
使用
当地时间
.我们可以用这种类型制作一个
departureUnzoned
类定义中的成员变量。我单独去了
本地日期
和
当地时间
作为构建块,以便您了解各个部分。许多程序员使用他们的直觉而不是文档来假设
LocalDateTime
表示某个位置的特定时刻,而实际上它的含义正好相反。(在堆栈溢出建议中,您会发现许多错误答案
LocalDateTime
实际上什么时候
Instant
或
ZonedDateTime
应使用。)
让我们添加一个方法来计算到达时间。
public class Flight {
private String flightNumber;
private LocalDate departureDateUnzoned;
private LocalTime departureTimeUnzoned;
private ZoneId departureZoneId;
private Duration duration;
public LocalDateTime arrivalDateTimeUnzoned () {
LocalDateTime departureUnzoned = LocalDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned );
LocalDateTime ldt = departureUnzoned.plus( this.duration );
return ldt;
}
}
但是这个回来了
LocalDateTime
无法说明时区。通常,航空公司和火车向客户报告调整到该地区时区的预期到达时间。所以我们需要一个到达时区。我们可以在计算到达时使用该区域,从而生成
ZonedDateTime
A.
分区DateTime
是
一个特定的时刻
是
时间线上的一个点,不像
LocalDateTime
但请记住,如果我们计划未来的航班
分区DateTime
如果我们的代码在政客重新定义时区后运行,将会发生变化。
public class Flight {
private String flightNumber;
private LocalDate departureDateUnzoned;
private LocalTime departureTimeUnzoned;
private ZoneId departureZoneId;
private Duration duration;
private ZoneId arrivalZoneId;
public ZonedDateTime arrivalDateTimeZoned () {
ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
ZonedDateTime zdt = departureZoned.plus( this.duration );
return zdt;
}
}
回到问题中关于自动确定日期的部分。这需要一个时区。在任何特定的时刻,全球各地的日期都不尽相同。想想看。午夜过后的几分钟,法国巴黎迎来了新的一天,而魁北克蒙特勒州仍然是昨天。
我们可以询问JVM当前的默认时区。
ZoneId userZoneId = ZoneId.systemDefault() ;
但在关键时刻,您必须与用户确认。
ZoneId userZoneId = ZoneId.of( "America/Montreal" ) ;
现在我们可以添加您要求的构造函数,通过一天中的时间(a
当地时间
,并使用JVM的当前默认值猜测时区。
但我们还需要所有其他的零件。因此,默认日期并不能为我们节省很多。
public class Flight {
private String flightNumber;
private LocalDate departureDateUnzoned;
private LocalTime departureTimeUnzoned;
private ZoneId departureZoneId;
private Duration duration;
private ZoneId arrivalZoneId;
// Constructor
public Flight ( String flightNumber , LocalTime departureTimeUnzoned , ZoneId departureZoneId , Duration duration , ZoneId arrivalZoneId ) {
this.flightNumber = flightNumber;
this.departureTimeUnzoned = departureTimeUnzoned;
this.departureZoneId = departureZoneId;
this.duration = duration;
this.arrivalZoneId = arrivalZoneId;
// Determine todayâs date using JVMâs current default time zone. Not advisable in many business scenarios, but specified by our Question at hand.
ZoneId z = ZoneId.systemDefault();
LocalDate today = LocalDate.now( z );
this.departureDateUnzoned = today;
}
public ZonedDateTime arrivalDateTimeZoned () {
ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
ZonedDateTime zdt = departureZoned.plus( this.duration );
return zdt;
}
}
让我们添加
toString
报告方法。
在标准中,我们将日期时间值表示为字符串
ISO 8601
格式。这个
JAVA时间
类在解析/生成字符串时使用这些标准格式。这个
Z
结尾处发音
Zulu
和方法
UTC
。
虽然航空公司和火车在地区时区向其客户报告日期时间,但我们可以假设他们在内部只使用UTC。这个
Instant
类具体表示UTC中的值。所以我们
toString公司
摘录
瞬间
中的对象
分区DateTime
对象。
我们添加了一个
main
演示方法。这是完整的课程
import
等
package com.basilbourque.example;
import java.time.*;
public class Flight {
private String flightNumber;
private LocalDate departureDateUnzoned;
private LocalTime departureTimeUnzoned;
private ZoneId departureZoneId;
private Duration duration;
private ZoneId arrivalZoneId;
// Constructor
public Flight ( String flightNumber , LocalTime departureTimeUnzoned , ZoneId departureZoneId , Duration duration , ZoneId arrivalZoneId ) {
this.flightNumber = flightNumber;
this.departureTimeUnzoned = departureTimeUnzoned;
this.departureZoneId = departureZoneId;
this.duration = duration;
this.arrivalZoneId = arrivalZoneId;
// Determine todayâs date using JVMâs current default time zone. Not advisable in many business scenarios, but specified by our Question at hand.
ZoneId z = ZoneId.systemDefault();
LocalDate today = LocalDate.now( z );
this.departureDateUnzoned = today;
}
public ZonedDateTime arrivalDateTimeZoned () {
ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
ZonedDateTime zdt = departureZoned.plus( this.duration );
return zdt;
}
@Override
public String toString () {
ZonedDateTime departureZoned = ZonedDateTime.of( this.departureDateUnzoned , this.departureTimeUnzoned , this.departureZoneId );
String flightInUtc = departureZoned.toInstant().toString() + "/" + this.arrivalDateTimeZoned().toInstant().toString();
return "Flight{ " +
"flightNumber='" + this.flightNumber + '\'' +
" | departureDateUnzoned=" + this.departureDateUnzoned +
" | departureTimeUnzoned=" + this.departureTimeUnzoned +
" | departureZoneId=" + this.departureZoneId +
" | departureZoned=" + departureZoned +
" | duration=" + this.duration +
" | arrivalZoneId=" + this.arrivalZoneId +
" | calculatedArrival=" + this.arrivalDateTimeZoned() +
" | flightInUtc=" + flightInUtc +
" }";
}
public static void main ( String[] args ) {
LocalTime lt = LocalTime.of( 6 , 0 ); // 6 AM.
Flight f = new Flight( "A472" , lt , ZoneId.of( "America/Los_Angeles" ) , Duration.parse( "PT6H37M" ) , ZoneId.of( "America/Montreal" ) );
String output = f.toString();
System.out.println( output );
}
}
运行时。
航班{flightNumber='A472'|出发日期未分区=2018-05-06 |出发时间未分区=06:00 |出发区域ID=美国/洛杉矶|出发区域ID=2018-05-06T06:00-07:00[美国/洛杉矶]|持续时间=PT6H37M |抵达区域ID=美国/蒙特利尔|计算到达时间=2018-05-06T12:37-07:00[美国/洛杉矶]|飞行TC=2018-05-INUINU 06T13:00:00Z/2018-05-06T19:37:00Z}
要从控制台使用此功能,请询问用户24小时制的时间。分析输入字符串。
String input = "14:56" ; // 24-hour clock.
LocalTime lt = LocalTime.parse( input ) ;
对于现实世界的工作来说,这还远远不够。但希望它能成为一个有教育意义的例子。
关于
JAVA时间
这个
java.time
框架内置于Java 8及更高版本中。这些课程取代了烦人的旧课程
legacy
日期时间类,如
java.util.Date
,则,
Calendar
,&
SimpleDateFormat
。
这个
Joda时间
项目,现在处于
maintenance mode
,建议迁移到
java.time
课程。
要了解更多信息,请参阅
Oracle Tutorial
。并搜索堆栈溢出以获取许多示例和解释。规格为
JSR 310
。
您可以交换
JAVA时间
对象直接与数据库连接。使用
JDBC driver
符合
JDBC 4.2
或更高版本。不需要字符串,不需要
java.sql.*
课程。
从何处获取java。时间课程?
这个
ThreeTen-Extra
project扩展了java。额外上课的时间。该项目是java未来可能添加内容的试验场。时间您可以在这里找到一些有用的类,例如
Interval
,则,
YearWeek
,则,
YearQuarter
和
more
。