获取 Java 日期或日历的时间组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1363307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting the Time component of a Java Date or Calendar
提问by Matt Ball
Is there a simple or elegant way to grab only the time of day (hours/minutes/seconds/milliseconds) part of a Java Date (or Calendar, it really doesn't matter to me)? I'm looking for a nice way to separately consider the date (year/month/day) and the time-of-day parts, but as far as I can tell, I'm stuck with accessing each field separately.
有没有一种简单或优雅的方法来获取 Java 日期(或日历,对我来说真的无关紧要)的一天中的时间(小时/分钟/秒/毫秒)部分?我正在寻找一种单独考虑日期(年/月/日)和时间部分的好方法,但据我所知,我一直坚持单独访问每个字段。
I know I could write my own method to individually grab the fields I'm interested, but I'd be doing it as a static utility method, which is ugly. Also, I know that Date and Calendar objects have millisecond precision, but I don't see a way to access the milliseconds component in either case.
我知道我可以编写自己的方法来单独获取我感兴趣的字段,但我会将其作为静态实用程序方法来执行,这很丑陋。另外,我知道 Date 和 Calendar 对象具有毫秒精度,但在任何一种情况下我都看不到访问毫秒组件的方法。
Edit:I wasn't clear about this: using one of the Date::getTime() or Calendar::getTimeInMillis is not terribly useful to me, since those return the number of milliseconds since the epoch (represented by that Date or Calendar), which does not actually separate the time of dayfrom the rest of the information.
编辑:我不清楚这一点:使用 Date::getTime() 或 Calendar::getTimeInMillis 之一对我来说并不是非常有用,因为它们返回自纪元以来的毫秒数(由该日期或日历表示) ,这实际上并没有将一天中的时间与其他信息分开。
@Jherico's answer is the closest thing, I think, but definitely is something I'd still have to roll into a method I write myself. It's not exactly what I'm going for, since it still includes hours, minutes, and seconds in the returned millisecond value - though I could probably make it work for my purposes.
@Jherico 的答案是最接近的,我认为,但绝对是我仍然必须采用我自己编写的方法。这并不完全是我想要的,因为它仍然在返回的毫秒值中包含小时、分钟和秒 - 尽管我可能会使其适合我的目的。
I still think of each component as separate, although of course, they're not. You can write a time as the number of milliseconds since an arbitrary reference date, or you could write the exact same time as year/month/day hours:minutes:seconds.milliseconds
.
我仍然认为每个组件都是独立的,当然,它们不是。您可以将时间写入自任意参考日期以来的毫秒数,或者您可以写入与year/month/day hours:minutes:seconds.milliseconds
.
This is not for display purposes. I know how to use a DateFormat
to make pretty date strings.
这不是用于显示目的。我知道如何使用 aDateFormat
来制作漂亮的日期字符串。
Edit 2:My original question arose from a small set of utility functions I found myself writing - for instance:
编辑 2:我最初的问题来自我发现自己编写的一小组实用函数 - 例如:
- Checking whether two
Date
s represent a date-time on the same day; - Checking whether a date is within a range specified by two other dates, but sometimes checking inclusively, and sometimes not, depending on the time component.
- 检查两个
Date
s是否代表同一天的日期时间; - 检查一个日期是否在其他两个日期指定的范围内,但有时检查包含性,有时不包含性检查,具体取决于时间组件。
Does Joda Time have this type of functionality?
Joda Time 有这种功能吗?
Edit 3:@Jon's question regarding my second requirement, just to clarify: The second requirement is a result of using my Dates to sometimes represent entire days - where the time component doesn't matter at all - and sometimes represent a date-time (which is, IMO, the most accurate word for something that contains year/month/day
andhours:minutes:seconds:...
).
编辑 3:@Jon 关于我的第二个要求的问题,只是为了澄清:第二个要求是使用我的日期有时代表一整天的结果 - 时间组件根本不重要 - 有时代表日期时间(也就是,IMO,对于包含year/month/day
和的事物最准确的词hours:minutes:seconds:...
)。
When a Date represents an entire day, its time parts are zero (e.g. the Date's "time component" is midnight) but the semantics dictate that the range check is done inclusively on the end date. Because I just leave this check up to Date::before and Date::after, I have to add 1 day to the end date - hence the special-casing for when the time-of-day component of a Date is zero.
当 Date 表示一整天时,它的时间部分为零(例如 Date 的“时间组件”是午夜),但语义规定范围检查在结束日期包含在内。因为我只是把这个检查留给 Date::before 和 Date::after,所以我必须在结束日期上加上 1 天 - 因此当日期的时间部分为零时的特殊情况。
Hope that didn't make things less clear.
希望这不会让事情变得不那么清楚。
采纳答案by Jon Skeet
Okay, I know this is a predictable answer, but... use Joda Time. That has separate representations for "a date", "an instant", "a time of day" etc. It's a richer API and a generally saner one than the built-in classes, IMO.
好的,我知道这是一个可预测的答案,但是...使用Joda Time。它对“日期”、“瞬间”、“一天中的某个时间”等有单独的表示。它是一个更丰富的 API,并且比内置类 IMO 更合理。
If this is the onlybit of date/time manipulation you're interested in then it may be overkill... but if you're using the built-in date/time API for anything significant, I'd stronglyrecommend that you move away from it to Joda as soon as you possibly can.
如果这是您唯一感兴趣的日期/时间操作,那么它可能有点矫枉过正……但是如果您将内置日期/时间 API 用于任何重要的事情,我强烈建议您移动尽快远离它到乔达。
As an aside, you should consider what time zone you're interested in. A Calendar
has an associated time zone, but a Date
doesn't (it just represents an instant in time, measured in milliseconds from the Unix epoch).
顺便说Calendar
一句,你应该考虑你感兴趣的时区。 A有一个关联的时区,但 aDate
没有(它只是代表一个瞬间,从 Unix 纪元开始以毫秒为单位)。
回答by PHeath
To answer part of it, accessing the millisecond component is done like this:
为了回答它的一部分,访问毫秒组件是这样完成的:
long mill = Calendar.getInstance().getTime();
I don't know what you want to do with the specifics, but you could use the java.text.SimpleDateFormat class if it is for text output.
我不知道你想对细节做什么,但如果它用于文本输出,你可以使用 java.text.SimpleDateFormat 类。
回答by Dan Polites
You can call the getTimeInMillis() function on a Calendar object to get the time in milliseconds. You can call get(Calendar.MILLISECOND) on a calendar object to get the milliseconds of the second. If you want to display the time from a Date or Calendar object, use the DateFormat class. Example: DateFormat.getTimeInstance().format(now). There is also a SimpleDateFormat class that you can use.
您可以在 Calendar 对象上调用 getTimeInMillis() 函数以获取以毫秒为单位的时间。您可以在日历对象上调用 get(Calendar.MILLISECOND) 以获取秒的毫秒数。如果要显示 Date 或 Calendar 对象的时间,请使用 DateFormat 类。示例:DateFormat.getTimeInstance().format(now)。您还可以使用 SimpleDateFormat 类。
回答by Jherico
Extracting the time portion of the day should be a matter of getting the remainder number of milliseconds when you divide by the number of milliseconds per day.
当您除以每天的毫秒数时,提取一天的时间部分应该是获得剩余毫秒数的问题。
long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
Date now = Calendar.getInstance().getTime();
long timePortion = now.getTime() % MILLIS_PER_DAY;
Alternatively, consider using joda-time, a more fully featured time library.
或者,考虑使用 joda-time,一个功能更齐全的时间库。
回答by Jay
If all you're worried about is getting it into a String for display or saving, then just create a SimpleDateFormat that only displays the time portion, like new SimpleDateFormat("HH:mm:ss"). The date is still in the Date object, of course, but you don't care.
如果您所担心的只是将其放入 String 以进行显示或保存,那么只需创建一个只显示时间部分的 SimpleDateFormat,例如 new SimpleDateFormat("HH:mm:ss")。当然,日期仍然在 Date 对象中,但您不在乎。
If you want to do arithmetic on it, like take two Date objects and find how many seconds apart they are while ignoring the date portion, so that "2009-09-01 11:00:00" minus "1941-12-07 09:00:00" equals 2 hours, then I think you need to use a solution like Jherico's: get the long time and take it module 1 day.
如果你想对它做算术,比如拿两个 Date 对象并找出它们相隔多少秒而忽略日期部分,这样“2009-09-01 11:00:00”减去“1941-12-07 09 :00:00" 等于 2 小时,那么我认为您需要使用 Jherico 之类的解决方案:获得很长的时间并在一天内完成模块。
回答by Bill K
Why do you want to separate them? If you mean to do any arithmetic with the time portion, you will quickly get into trouble. If you pull out 11:59pm and add a minute, now that your time and day are separate, you've screwed yourself--you'll have an invalid time and an incorrect date.
为什么要把它们分开?如果您打算对时间部分进行任何算术运算,您很快就会陷入困境。如果您退出晚上 11:59 并增加一分钟,那么既然您的时间和日期是分开的,那么您就搞砸了——您将拥有无效的时间和错误的日期。
If you just want to display them, then applying various simple date format's should get you exactly what you want.
如果您只想显示它们,那么应用各种简单的日期格式应该可以满足您的需求。
If you want to manipulate the date, I suggest you get the long values and base everything off of that. At any point you can take that long and apply a format to get the minutes/hours/seconds to display pretty easily.
如果你想操纵日期,我建议你获取长值并以此为基础。在任何时候,您都可以花那么长时间并应用一种格式来轻松显示分钟/小时/秒。
But I'm just a little concerned with the concept of manipulating day and time separately, seems like opening a can o' worms. (Not to even mention time zone problems!).
但我只是有点担心分别操纵日期和时间的概念,这似乎是在打开一个蠕虫罐头。(更不用说时区问题了!)。
I'm fairly sure this is why Java doesn't have an easy way to do this.
我很确定这就是为什么 Java 没有简单的方法来做到这一点。
回答by Basil Bourque
To get just the time using Joda-Time, use the org.joda.time.LocalTime
class as described in this question, Joda-Time, Time without date.
要使用 Joda-Time 获取时间,请使用org.joda.time.LocalTime
此问题中描述的类Joda-Time, Time without date。
As for comparing dates only while effectively ignoring time, in Joda-Time call the withTimeAtStartOfDay()
method on each DateTime
instance to set an identical time value. Here is some example code using Joda-Time 2.3, similar to what I posted on another answer today.
至于只比较日期而有效地忽略时间,在 Joda-Time 中调用withTimeAtStartOfDay()
每个DateTime
实例上的方法来设置相同的时间值。这是一些使用 Joda-Time 2.3 的示例代码,类似于我今天在另一个答案中发布的内容。
// ? 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/
// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310
// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601
// Capture one moment in time.
org.joda.time.DateTime now = new org.joda.time.DateTime();
System.out.println("Now: " + now);
// Calculate approximately same time yesterday.
org.joda.time.DateTime yesterday = now.minusDays(1);
System.out.println("Yesterday: " + yesterday);
// Compare dates. A DateTime includes time (hence the name).
// So effectively eliminate the time by setting to start of day.
Boolean isTodaySameDateAsYesterday = now.withTimeAtStartOfDay().isEqual(yesterday.withTimeAtStartOfDay());
System.out.println("Is today same date as yesterday: " + isTodaySameDateAsYesterday);
org.joda.time.DateTime halloweenInUnitedStates = new org.joda.time.DateTime(2013, 10, 31, 0, 0);
Boolean isFirstMomentSameDateAsHalloween = now.withTimeAtStartOfDay().isEqual(halloweenInUnitedStates.withTimeAtStartOfDay());
System.out.println("Is now the same date as Halloween in the US: " + isFirstMomentSameDateAsHalloween);
回答by Richard Gomes
Find below a solution which employs Joda Time and supports time zones.
So, you will obtain date and time (into currentDate
and currentTime
) in the currently configured timezone in the JVM.
在下面找到一个使用 Joda 时间并支持时区的解决方案。因此,您将在 JVM 中当前配置的时区中获取日期和时间(进入currentDate
和currentTime
)。
Please notice that Joda Time does not support leap seconds. So, you can be some 26 or 27 seconds off the true value. This probably will only be solved in the next 50 years, when the accumulated error will be closer to 1 min and people will start to care about it.
请注意 Joda Time 不支持闰秒。因此,您可能与真实值相差 26 或 27 秒。这可能要在未来 50 年才能解决,届时累积误差将接近 1 分钟,人们将开始关心它。
See also: https://en.wikipedia.org/wiki/Leap_second
另见:https: //en.wikipedia.org/wiki/Leap_second
/**
* This class splits the current date/time (now!) and an informed date/time into their components:
* <lu>
* <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
* <li>informedDate: the date (only) part of the informed date/time</li>
* <li>informedTime: the time (only) part of the informed date/time</li>
* <li>currentDate: the date (only) part of the current date/time (now!)</li>
* <li>currentTime: the time (only) part of the current date/time (now!)</li>
* </lu>
*/
public class ScheduleDateTime {
public final boolean schedulable;
public final long millis;
public final java.util.Date informedDate;
public final java.util.Date informedTime;
public final java.util.Date currentDate;
public final java.util.Date currentTime;
public ScheduleDateTime(long millis) {
final long now = System.currentTimeMillis();
this.schedulable = (millis > -1L) && (millis >= now);
final TimeZoneUtils tz = new TimeZoneUtils();
final java.util.Date dmillis = new java.util.Date( (millis > -1L) ? millis : now );
final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdmillis = java.util.Date.from(tz.tzdate(zdtmillis));
final java.util.Date ztmillis = new java.util.Date(tz.tztime(zdtmillis));
final java.util.Date dnow = new java.util.Date(now);
final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdnow = java.util.Date.from(tz.tzdate(zdtnow));
final java.util.Date ztnow = new java.util.Date(tz.tztime(zdtnow));
this.millis = millis;
this.informedDate = zdmillis;
this.informedTime = ztmillis;
this.currentDate = zdnow;
this.currentTime = ztnow;
}
}
public class TimeZoneUtils {
public java.time.Instant tzdate() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tzdate(zdtime);
}
public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final java.time.Instant instant = zddate.toInstant();
return instant;
}
public long tztime() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tztime(zdtime);
}
public long tztime(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
return millis;
}
}
回答by Basil Bourque
tl;dr
tl;博士
LocalTime lt = myUtilDate.toInstant().atZone( ZoneId.of( "America/Montreal" ) ).toLocalTime() ;
Avoid old date-time classes
避免旧的日期时间课程
You are using old legacy date-time classes. They are troublesome and confusing; avoid them.
您正在使用旧的遗留日期时间类。它们既麻烦又令人困惑;避免它们。
Instead use java.time classes. These supplant the old classes as well as the Joda-Time library.
而是使用 java.time 类。这些取代了旧类以及 Joda-Time 库。
Convert
转变
Convert your java.util.Date
to an Instant
.
将您的转换java.util.Date
为Instant
.
The Instant
class represents a moment on the timeline in UTCwith a resolution of nanoseconds.
Instant instant = myUtilDate.toInstant();
Time Zone
时区
Apply a time zone. Time zone is crucial. For any given moment the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while also being “yesterday” in Montréal Québec.
应用时区。时区至关重要。对于任何给定时刻,日期因地区而异。例如,在法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔也是“昨天”。
Apply a ZoneId
to get a ZonedDateTime
object.
应用 aZoneId
来获取一个ZonedDateTime
对象。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Local…
types
Local…
类型
The LocalDate
class represents a date-only value without time-of-day and without time zone. Likewise, the LocalTime
represents a time-of-day without a date and without a time zone. You can think of these as two components which along with a ZoneId
make up a ZonedDateTime
. You can extract these from a ZonedDateTime
.
该LocalDate
级表示没有时间一天和不同时区的日期,唯一的价值。同样,LocalTime
表示没有日期和时区的时间。您可以将它们视为两个组件,它们与ZoneId
一个ZonedDateTime
. 您可以从ZonedDateTime
.
LocalDate ld = zdt.toLocalDate();
LocalTime lt = zdt.toLocalTime();
Strings
字符串
If your goal is merely generating Strings for presentation to the user, no need for the Local…
types. Instead, use DateTimeFormatter
to generate strings representing only the date-portion or the time-portion. That class is smart enough to automatically localizewhile generating the String.
如果您的目标只是生成字符串以呈现给用户,则不需要Local…
类型。相反,用于DateTimeFormatter
生成仅表示日期部分或时间部分的字符串。该类足够智能,可以在生成字符串时自动进行本地化。
Specify a Locale
to determine (a) the human language used for translating name of day, name of month, and such, and (b) the cultural norms for deciding issues such as abbreviation, capitalization, punctuation, and such.
指定 aLocale
以确定 (a) 用于翻译日名、月名等的人类语言,以及 (b) 决定缩写、大写、标点等问题的文化规范。
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter fDate = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale );
String outputDate = zdt.format( fDate );
DateTimeFormatter fTime = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ).withLocale( locale );
String outputTime = zdt.format( fTime );
About java.time
关于 java.time
The java.timeframework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了旧的麻烦的日期时间类,例如java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to java.time.
现在处于维护模式的Joda-Time项目建议迁移到 java.time。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backportand further adapted to Androidin ThreeTenABP(see How to use…).
大部分的java.time功能后移植到Java 6和7 ThreeTen,反向移植,并进一步用于安卓在ThreeTenABP(见如何使用......)。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。
回答by Freelancer
Using Calendar API -
使用日历 API -
Solution 1-
解决方案1-
Calendar c = Calendar.getInstance();
String timeComp = c.get(Calendar.HOUR_OF_DAY)+":"+c.get(Calendar.MINUTE)+":"+c.get(Calendar.SECOND)+":"+c.get(Calendar.MILLISECOND);
System.out.println(timeComp);
output- 13:24:54:212
输出- 13:24:54:212
Solution 2-
解决方案2-
SimpleDateFormat time_format = new SimpleDateFormat("HH:mm:ss.SSS");
String timeComp = time_format.format(Calendar.getInstance().getTime());
output- 15:57:25.518
输出- 15:57:25.518