如何获取一天的开始时间和结束时间?
像这样的代码不准确: private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
毫秒不准确。
答案 0 :(得分:130)
public static Date atStartOfDay(Date date) {
LocalDateTime localDateTime = dateToLocalDateTime(date);
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
return localDateTimeToDate(startOfDay);
}
public static Date atEndOfDay(Date date) {
LocalDateTime localDateTime = dateToLocalDateTime(date);
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
return localDateTimeToDate(endOfDay);
}
private static LocalDateTime dateToLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
private static Date localDateTimeToDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
更新:我已将这两种方法添加到我的Java Utility类here
它位于Maven Central Repository:
<dependency>
<groupId>com.github.rkumsher</groupId>
<artifactId>utils</artifactId>
<version>1.3</version>
</dependency>
public static Date atEndOfDay(Date date) {
return DateUtils.addMilliseconds(DateUtils.ceiling(date, Calendar.DATE), -1);
}
public static Date atStartOfDay(Date date) {
return DateUtils.truncate(date, Calendar.DATE);
}
public Date atEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
return calendar.getTime();
}
public Date atStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
答案 1 :(得分:78)
answer by mprivat是正确的。他的观点是不要试图获得一天的结束,而是要比较“在第二天开始之前”。他的想法被称为“半开放式”方法,其中一段时间的开头是包容性的,而结尾是独占的。
Joda-Time 2.3为此目的提供了一种方法,以获取当天的第一时刻:withTimeAtStartOfDay()
。同样在java.time中,LocalDate::atStartOfDay
。
Search StackOverflow for "joda half-open"了解更多讨论和示例。
请参阅Bill Schneider撰写的这篇文章Time intervals and other ranges should be half-open。
java.util.Date和.Calendar类非常麻烦。避免他们。
使用Joda-Time或最好使用java.time。 java.time框架是非常成功的Joda-Time库的官方继承者。
java.time框架内置于Java 8及更高版本中。后端移植到Java 6&amp; ThreeTen-Backport项目中的7,在ThreeTenABP项目中进一步适应Android。
Instant
是UTC中时间轴上的一个时刻,分辨率为nanoseconds。
Instant instant = Instant.now();
应用时区以获取某个地区的wall-clock time。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
要获得当天的第一时间,请查看LocalDate
课程及其atStartOfDay
方法。
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
使用半开放式方法,获得第二天的第一时刻。
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
目前,java.time框架缺少一个Interval
类,如下面针对Joda-Time所述。但是,ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。其中的课程是Interval
。通过传递一对Interval
对象构造Instant
。我们可以从Instant
个对象中提取ZonedDateTime
。
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
更新:Joda-Time项目现在处于维护模式,并建议迁移到 java.time 类。我将这段保留完整的历史记录。
Joda-Time有三个类,以各种方式表示时间跨度:Interval
,Period
和Duration
。 Interval
具有特定的开始和结束于宇宙的时间轴。这符合我们代表“一天”的需要。
我们调用方法withTimeAtStartOfDay
而不是将时间设置为零。由于夏令时和其他异常情况,当天的第一时刻可能不是00:00:00
。
使用Joda-Time 2.3的示例代码。
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTime todayStart = now.withTimeAtStartOfDay();
DateTime tomorrowStart = now.plusDays( 1 ).withTimeAtStartOfDay();
Interval today = new Interval( todayStart, tomorrowStart );
如果必须,您可以转换为java.util.Date。
java.util.Date date = todayStart.toDate();
答案 2 :(得分:25)
在getEndOfDay中,您可以添加:
calendar.set(Calendar.MILLISECOND, 999);
虽然从数学角度讲,除了说“在第二天开始之前”之外,你不能指定一天结束。
所以,不要说if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
,而应该说:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
。这是一个更加可靠的定义(您不必担心毫秒精度)。
答案 3 :(得分:7)
使用Java 8中内置的java.time
框架。
import java.time.LocalTime;
import java.time.LocalDateTime;
LocalDateTime now = LocalDateTime.now(); // 2015-11-19T19:42:19.224
// start of a day
now.with(LocalTime.MIN); // 2015-11-19T00:00
now.with(LocalTime.MIDNIGHT); // 2015-11-19T00:00
// end of a day
now.with(LocalTime.MAX); // 2015-11-19T23:59:59.999999999
答案 4 :(得分:2)
最短的答案,因为您的时区是 TZ
:
LocalDateTime start = LocalDate.now(TZ).atStartOfDay()
LocalDateTime end = start.plusDays(1)
比较使用 isAfter()
和 isBefore()
方法,或者使用 toEpochSecond()
或 toInstant()
方法进行转换。
答案 5 :(得分:2)
使用java8 java.time.ZonedDateTime而不是通过LocalDateTime
查找一天开始的其他方法只是将输入ZonedDateTime截断为DAYS:
zonedDateTimeInstance.truncatedTo( ChronoUnit.DAYS );
答案 6 :(得分:2)
对于java 8,以下单行语句正在运行。在这个例子中,我使用UTC时区。请考虑更改您当前使用的TimeZone。
System.out.println(new Date());
final LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
final Date endOfDayAsDate = Date.from(endOfDay.toInstant(ZoneOffset.UTC));
System.out.println(endOfDayAsDate);
final LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
final Date startOfDayAsDate = Date.from(startOfDay.toInstant(ZoneOffset.UTC));
System.out.println(startOfDayAsDate);
如果与输出没有时差。尝试:ZoneOffset.ofHours(0)
答案 7 :(得分:1)
另一个不依赖于任何框架的解决方案是:
static public Date getStartOfADay(Date day) {
final long oneDayInMillis = 24 * 60 * 60 * 1000;
return new Date(day.getTime() / oneDayInMillis * oneDayInMillis);
}
static public Date getEndOfADay(Date day) {
final long oneDayInMillis = 24 * 60 * 60 * 1000;
return new Date((day.getTime() / oneDayInMillis + 1) * oneDayInMillis - 1);
}
请注意,它会返回基于UTC的时间
答案 8 :(得分:1)
ZonedDateTime curDate = ZonedDateTime.now();
public ZonedDateTime startOfDay() {
return curDate
.toLocalDate()
.atStartOfDay()
.atZone(curDate.getZone())
.withEarlierOffsetAtOverlap();
}
public ZonedDateTime endOfDay() {
ZonedDateTime startOfTomorrow =
curDate
.toLocalDate()
.plusDays(1)
.atStartOfDay()
.atZone(curDate.getZone())
.withEarlierOffsetAtOverlap();
return startOfTomorrow.minusSeconds(1);
}
// based on https://stackoverflow.com/a/29145886/1658268
LocalDateTime curDate = LocalDateTime.now();
public LocalDateTime startOfDay() {
return curDate.atStartOfDay();
}
public LocalDateTime endOfDay() {
return startOfTomorrow.atTime(LocalTime.MAX); //23:59:59.999999999;
}
// based on https://stackoverflow.com/a/36408726/1658268
我希望能帮助别人。
答案 9 :(得分:1)
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.setTimeInMillis(0);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.setTimeInMillis(0);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
calendar.setTimeInMillis(0); 使您的准确度达到毫秒级
答案 10 :(得分:0)
我尝试了这段代码,效果很好!
final ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
final ZonedDateTime startofDay =
now.toLocalDate().atStartOfDay(ZoneOffset.UTC);
final ZonedDateTime endOfDay =
now.toLocalDate().atTime(LocalTime.MAX).atZone(ZoneOffset.UTC);
答案 11 :(得分:0)
我知道这有点晚了,但是对于Java 8,如果您使用的是OffsetDateTime(它具有很多优势,例如TimeZone,Nanoseconds等),则可以使用以下代码:
require "colorize"
class Filecalculation
def initialize
@books = "You can use this knowledge to create small tools that might help you."
end
def calc_1 paragraph
word_count = paragraph.strip.squeeze(' ').count(' ') + 1
puts "#{word_count} words"
end
def select
loop do
puts "# Will we search : Calculation_lines paragraph(1)".cyan
print "\n>>>>>> ".yellow
input = gets.chomp
search_method = "calc_#{input}" #.to_sym
if (respond_to?(search_method))
contents = send(search_method, @books)
else
puts "exit "
exit
end
end
end
end
Filecalculation.new.select
答案 12 :(得分:0)
我对所有解决方案都有一些不便之处,因为我需要 Instant 变量的类型,并且时区总是干扰更改所有内容,因此结合解决方案我发现这是一个不错的选择。
LocalDate today = LocalDate.now();
Instant startDate = Instant.parse(today.toString()+"T00:00:00Z");
Instant endDate = Instant.parse(today.toString()+"T23:59:59Z");
结果就是我们
startDate = 2020-01-30T00:00:00Z
endDate = 2020-01-30T23:59:59Z
希望对您有帮助
答案 13 :(得分:0)
我认为最简单的方法是:
// Joda Time
DateTime dateTime=new DateTime();
StartOfDayMillis = dateTime.withMillis(System.currentTimeMillis()).withTimeAtStartOfDay().getMillis();
EndOfDayMillis = dateTime.withMillis(StartOfDayMillis).plusDays(1).minusSeconds(1).getMillis();
然后可以根据您对Joda Time的要求,将这些毫秒数转换为Calendar,Instant或LocalDate。
答案 14 :(得分:0)
//this will work for user in time zone MST with 7 off set or UTC with saving time
//I have tried all the above and they fail the only solution is to use some math
//the trick is to rely on $newdate is time() //strtotime is corrupt it tries to read to many minds
//convert to time to use with javascript*1000
$dnol = strtotime('today')*1000;
$dn = ($newdate*1000)-86400000;
$dz=$dn/86400000; //divide into days
$dz=floor($dz); //filter off excess time
$dzt=$dz*86400000; // put back into days UTC
$jsDate=$dzt*1+(7*3600000); // 7 is the off set you can store the 7 in database
$dzt=$dzt-3600000; //adjusment for summerTime UTC additional table for these dates will drive you crazy
//solution get users [time off sets] with browser, up date to data base for user with ajax when they ain't lookin
<?php
$t=time();
echo($t . "<br>");
echo(date("Y-m-d",$t));
echo '<BR>'.$dnol;
echo '<BR>'.$dzt.'<BR>';
echo(date("Y-m-d",$dzt/1000)); //convert back for php /1000
echo '<BR>';
echo(date('Y-m-d h:i:s',$dzt/1000));
?>
答案 15 :(得分:0)
以下代码采用 OP 的原始公式,并针对 ms 的不精确性进行了调整:
private static Date getStartOfDay() {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
long approximateTimestamp = calendar.getTime().getTime();
long extraMillis = (approximateTimestamp % 1000);
long exactTimestamp = approximateTimestamp - extraMillis;
return new Date(exactTimestamp);
}
private static Date getEndOfDay() {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
long approximateTimestamp = calendar.getTime().getTime();
long extraMillis = (approximateTimestamp % 1000);
long exactTimestamp = approximateTimestamp - extraMillis + 999;
return new Date(exactTimestamp);
}
与此线程上的许多其他答案不同,它与旧版本的 Java 和 Android API 兼容。
答案 16 :(得分:-2)
public static Date beginOfDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
public static Date endOfDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
return cal.getTime();
}
答案 17 :(得分:-3)
我试过这段代码,效果很好! :
Date d= new Date();
GregorianCalendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
String s_d=d.getYear()+"-"+(d.getMonth()+1)+"-"+d.getDay();
DateFormat dateFormat = DateFormat.getDateInstance();
try {
// for the end of day :
c.setTime(dateFormat.parse(s_d+" 23:59:59"));
// for the start of day:
//c.setTime(dateFormat .parse(s_d+" 00:00:00"));
} catch (ParseException e) {
e.printStackTrace();
}