java获取date的年月日(java中获取当前时间的方法)
前言
上一周在做一个产品的需求的时候有个动态计算时间段(如现在是13:00,则时间段为15:10-17:10、17:10-19:10、19:10-21:10;即最早的出发时间为当前时间+参数【2h10min】,最迟的时间段为开始时间在20点前结束时间在20点后的时间段),期间大量使用到了日期时间类库,本着熟悉日期时间类库才有了这篇文章,文章最后我会把我如何实现的这个需求的一个算法贴出来。
一、JDK8以前版本中的时间类库
1.1 原始时间类库存在的缺陷与不足
我们在使用Java8之前的类库时,都会在处理日期-时间的时候总是不爽,这其中包括且不限于以下的槽点:
在Java 1.0版本中,对时间、日期的操作完全依赖于 java.util.Data 类,只能以毫秒的精度表示时间,无法表示日期。
- 在易用性方面有着很大的缺陷,年份的起始时间选择是1900年,月份是从0开始。
- toString 方法返回值不直观,带有时区。
在Java1.1 版本中,废弃了很多Date 类中的很多方法,并且新增了 java.util.Calendar。但是与Date相同,Calendar 类也有类似的问题和设计缺陷,导致在使用这些类写出的代码也很容易出错。
- 月份依然是从0开始计算。
- 常用的日期、时间操作需要同时使用Date、Canendar、SimpleDateFormat,比较繁琐。
- 部分特性只存在于某一个类(解析和格式化日期或时间的DateFormat方法只存在于Date类中)。
- DateFormat 不是线程安全的,如果两个线程尝试使用同一个formatter 解析日期,可能会得到无法预期的结果。
- Date 和 Canendar 都是可变的。
1.2 关于SimpleDateFormat 线程不安全的原因
由于 parse 方法使用的贡献变量 calendar 不是线程安全的。在 format (subFormat) 方法中进行了 calendar 的赋值,在 parse 进行了值得处理,因此在并发的情况下会造成 calendar 清理不及时,值被覆盖的情况。
/**
*The{@linkCalendar}instanceusedforcalculatingthedate-timefields
*andtheinstantoftime.Thisfieldisusedforbothformattingand
*parsing.
*
*<p>Subclassesshouldinitializethisfieldtoa{@linkCalendar}
*appropriateforthe{@linkLocale}associatedwiththis
*<code>DateFormat</code>.
*@serial
*/
protectedCalendarcalendar;
@Override
publicStringBufferformat(Datedate,StringBuffertoAppendTo,
FieldPositionpos){
pos.beginIndex=pos.endIndex=0;
returnformat(date,toAppendTo,pos.getFieldDelegate());
}
//CalledfromFormataftercreatingaFieldDelegate
privateStringBufferformat(Datedate,StringBuffertoAppendTo,
FieldDelegatedelegate){
//Convertinputdatetotimefieldlist
calendar.setTime(date);
//AtthispointthefieldsofCalendarhavebeenset.Calendar
//willfillindefaultvaluesformissingfieldswhenthetime
//iscomputed.
pos.index=start;
DateparsedDate;
try{
parsedDate=calb.establish(calendar).getTime();
//Iftheyearvalueisambiguous,
//thenthetwo-digityear==thedefaultstartyear
if(ambiguousYear[0]){
if(parsedDate.before(defaultCenturyStart)){
parsedDate=calb.addYear(100).establish(calendar).getTime();
}
}
}
}
1.3 如何解决上述线程不安全问题?
- 使用ThreadLocal 为每个线程都创建一个线程独享 SimpleDateFormat 变量;
- 需要的时候创建局部变量;
- 使用 org.apacle.commons.lang3.time.DateFormatUtils
- 使用Joda-Time (后面介绍)
二、Joda-Time 日期时间类库
2.1 简介
Joda-Time 是Joda提供的一个遵循Apache2.0 开源协议的 JDK以外的优质日期和时间开发库。
Joda除Joda-Time之外的项目有Joda-Money、Joda-Beans、Joda-Convert、Joda-Collect Joda官网
2.1.1 为什么使用Joda-Time
- 使用方便:Calendar 访问“正常的”日期困难,并且缺乏简单的防腐,Joda-Time 拥有简单的字段访问,比如获得年的 getYear() 和 获得星期 中的天 getDayOfWeek() 。
- 易于扩展:JDK支持通过使用子类实现多个日历系统,但是这是非常笨重的,并且在实现中很难选出另一个日历系统。Joda-Time 支持基于 Chronology 类实现多个可插拔的日历系统。
- 功能全面:Joda-Time 提供了所有的日期和时间计算的必须功能,它提供了即装即用的特性。
- 最新的时区计算:时区的实现基于公共时区信息数据库,每年更新数次。新版本的Joda-Time 包括了这个数据库的所有更改,应尽早进行必要的更新,手动更新区域数据很容易。
- 日历支持:提供了8种日历系统。
- 互通性:内部使用毫秒进行标识,这与JDK或者其他公共的时间表示相一致。
- 性能良好:支持针对所有访问的域进行最小的计算。
- 良好的测试覆盖率:有全方位的测试人员保证库的质量、
- 具有完整文档:有一个完整的用户指南,该指南提供了一个概述,涵盖常见的使用场景。javadoc 非常详细,涵盖API的其余部分。
- 发展:自2002年以来积极发展,是一个成熟的可靠的代码库,一些相关的项目目前也是可用的。
- 开源:遵循Apache 2.0开源协议发布。
2.1.2 Joda-Time 的关键优点
- LocalDate:只包含日期
- LocalTime:只包含时间
- Instant:时间轴上的时间点
- DateTime:时区中完整的日期和时间
- DateTimeZone:更好的时区
- Duration和Period:持续时间
- Interval:两个时间点之间的时间
- 全面并且灵活的时间格式化与转换
正因为Joda-Time 与 Java8 之前的时间类库相比,具备了如此多的优点,所以 Joda-Time 成为事实上的标准的Java日期和时间库。
2.2 特性解读
2.2.1 Joda-Time和JDK的互操作性
互操作性是指:Joda 类能够生成 java.util.Date 的实例(以及Calendar),这可以让我们保留现有对JDK的依赖,又能够使用Joda处理复杂的日期/时间计算。
Date To Joda-Time
Datedate=newDate();
DateTimedateTime=newDateTime(date);
Canendar To Joda-Time
Calendarcalendar=Calendar.getInstance();
DateTimedateTime=newDateTime(calendar);
Joda-Time To Date
Datedate=newDate();
DateTimedateTime=newDateTime(date);
Datedate2=dateTime.toDate();
Joda-Time To Calendar
Calendarcalendar=Calendar.getInstance();
dateTime=newDateTime(calendar);
Calendarcalendar2=dateTime.toCalendar(Locale.CHINA);
2.2.2 Joda的关键日期/时间概念理解
Joda 使用了以下概念,使得它们可以应用到任何日期/时间库:
不可变性(Immutability)
Joda-Time与java.lang.String类似,它们的实例均无法修改(因为任意对其值改变的操作都会生成新的对象),这也代表了它们是线程安全的。
瞬时性(Instant)
如接口 org.joda.time.ReadableInstant 中所表示的那样,Instant 表示的是一个精确的时间点,是从 epoch:1970-01-01T00:00:00Z 开始计算的毫秒数,这也的设计也使得其子类都可以与JDK Date 以及 Calendar 类兼容。
/**
*Definesaninstantinthedatetimecontinuum.
*Thisinterfaceexpressesthedatetimeasmillisecondsfrom1970-01-01T00:00:00Z.
*<p>
*Theimplementationofthisinterfacemaybemutableorimmutable.
*Thisinterfaceonlygivesaccesstoretrievedata,nevertochangeit.
*<p>
*Methodsinyourapplicationshouldbedefinedusing<code>ReadableInstant</code>
*asaparameterifthemethodonlywantstoreadtheinstantwithoutneedingtoknow
*thespecificdatetimefields.
*<p>
*The{@codecompareTo}methodisnolongerdefinedinthisclassinversion2.0.
*Instead,thedefinitionissimplyinheritedfromthe{@codeComparable}interface.
*Thisapproachisnecessarytopreservebinarycompatibility.
*Thedefinitionofthecomparisonisascendingorderbymillisecondinstant.
*Implementorsarerecommendedtoextend{@codeAbstractInstant}insteadofthisinterface.
*
*@authorStephenColebourne
*@since1.0
*/
publicinterfaceReadableInstantextendsComparable<ReadableInstant>{
/**
*Getthevalueasthenumberofmillisecondssince
*theepoch,1970-01-01T00:00:00Z.
*
*@returnthevalueasmilliseconds
*/
longgetMillis();
······
}
DateTime 类继承图如下:

局部性(Partial)
瞬时性表达的是与epoch相对的时间上的一个精确时刻,而一个局部时间指的是一个时间的一部分片段,其可以通过一些方法使得时间产生变动(本质上还是生成了新的类),这样可以把它当做重复周期中的一点,用到多个地方。
年表(Chronology)
Joda-Time的设计核心就是年表(org.joda.time.Chronology),从根本上将,年表是一种日历系统,是一种计算时间的特殊方式,并且在其中执行日历算法的框架。Joda-Time支持的8种年表如下所示:
- ISO(默认) – org.joda.time.chrono.ISOChronology
- GJ – org.joda.time.chrono.GJChronology
- Gregorian – org.joda.time.chrono.GregorianChronology
- Julian – org.joda.time.chrono.JulianChronology
- Coptic – org.joda.time.chrono.CopticChronology
- Buddhist – org.joda.time.chrono.BuddhistChronology
- Ethiopic – org.joda.time.chrono.EthiopicChronology
- Islamic – org.joda.time.chrono.IslamicChronology
以上的每一种年表都可以作为特定日历系统的计算引擎,是可插拔的实现。
时区(Time zone)
具体定义详见百科解释,在实际编码过程中任何严格的时间计算都必须涉及时区(或者相对于GMT),Joda-Time中对应的核心类为org.joda.time.DateTimeZone,虽然日常的使用过程中,并未涉及到对时区的操作,但是DateTimeZone如何对DateTime产生影响是比较值得注意的,此处不进行赘述。
2.3 具体使用方法
上面介绍我完了Joda-Time的一些概念,接下来具体使用我们来进行说明:
2.3.1 创建 Joda-Time 对象
瞬时性-ReadableInstant
//1.使用系统时间
DateTimedateTime1=newDateTime();
//2.使用jdk中的date
DatejdkDate1=newDate();
DateTimedateTime2=newDateTime(jdkDate1);
//3.使用毫秒数指定
DatejdkDate2=newDate();
longmillis=jdkDate.getTime();
DateTimedateTime3=newDateTime(millis);
//4.使用Calendar
Calendarcalendar=Calendar.getInstance();
DateTimedateTime4=newDateTime(calendar);
//5.使用多个字段指定一个瞬间时刻(局部时间片段)
//yearmonthdayhour(midnightiszero)minutesecondmilliseconds
DateTimedateTime5=newDateTime(2000,1,1,0,0,0,0);
//6.由一个DateTime生成另一个DateTime
DateTimedateTime6=newDateTime(dateTime1);
//7.有时间字符串生成DateTime
StringtimeString="2019-01-01T00:00:00-06:00";
DateTimedateTime7=DateTime.parse(timeString);
局部性-ReadablePartial
当程序中处理的日期、时间并不需要是完整时刻的时候,可以创建一个局部时间,比如只希望专注于年/月/日, 或者一天中的时间,或者是一周中的某天。Joda-Time中有表示这些时间的是org.joda.time.ReadablePartial接口,实现它的两个类LocalDate和LocalTime是分别用来表示年/月/日和一天中的某个时间的。
//显示地提供所含的每个字段
LocalDatelocalDate=newLocalDate(2019,1,1);
//6:30:06PM
LocalTimelocalTime=newLocalTime(18,30,6,0);
LocalDate是替代了早期Joda-Time版本中使用的org.joda.time.YearMonthDay,LocalTime是替代早期版本的org.joda.time.TimeOfDay。(均已被标注为过时状态)。
时间跨度
Joda-Time提供了三个类用于表示时间跨度(在某些业务需求中,它们可能会非常有用)。
- Duration
这个类表示以毫秒为单位的绝对精度,提供标准数学转换的方法,同时把时间跨度转换为标准单位。
- Period
这个类表示以年月日单位表示。
- Interval
这个类表示一个特定的时间跨度,使用一个明确的时刻界定这段时间跨度的范围。Interval 为半开 区间,所以由其封装的时间跨度包括这段时间的起始时刻,但是不包含结束时刻。
2.3.2 使用Joda-Time的方法处理时间
DateTimetoday=newDateTime();
//获取777秒之前的时间
DateTimedateTime1=today.minus(777*1000);
//获取明天的时间
DateTimetomorrow=today.plusDays(1);
//获取当月第一天的日期
DateTimedateTime2=today.withDayOfMonth(1);
//获取当前时间三个月后的月份的最后一天
DateTimedateTime3=today.plusMonths(3).dayOfMonth().withMaximumValue();
下面列出部分DateTime方法列表: plus/minus开头的方法(比如:plusDay, minusMonths):用来返回在DateTime实例上增加或减少一段时间后的实例
- plus(long duration) 增加指定毫秒数并返回
- plusYears(int years) 增加指定年份并返回
- plusMonths(int months) 增加指定月份并返回
- plusWeeks(int weeks) 增加指定星期并返回
- plusDays(int days) 增加指定天数并返回
- plusHours(int hours) 增加指定小时并返回
- plusMinutes(int minutes) 增加指定分钟并返回
- plusSeconds(int seconds) 增加指定秒数并返回
- plusMillis(int millis) 增加指定毫秒并返回
与之相反的是minus前缀的 plus是增加 minus是减少
with开头的方法:用来返回在DateTime实例更新指定日期单位后的实例
- withCenturyOfEra(int centuryOfEra) 更新时间世纪单位并返回
- withYearOfCentury(int yearOfCentury)更新世纪年并返回
- withYear(int year) 更新时间年并返回
- withWeekyear(int weekyear) 更新时间周数并返回
- withMonthOfYear(int monthOfYear)更新时间月份并返回
- withDayOfYear(int dayOfYear) 更新时间天数并返回
- withDayOfMonth(int dayOfMonth) 更新时间天数并返回
- withDayOfWeek(int dayOfWeek) 更新时间天数并返回
- withHourOfDay(int hour) 更新时间小时并返回
- withMinuteOfHour(int minute) 更新时间分钟并返回
- withSecondOfMinute(int second) 更新时间秒数并返回
- withMillisOfSecond(int millis) 更新时间毫秒并返回
- withMillisOfDay(int millis) 更新时间毫秒并返回
- withTimeAtStartOfDay() 获取当天最早时间
判断DateTime对象大小状态的一些操作方法
- compareTo(DateTime d) 比较两时间大小 时间大于指定时间返回 1 时间小于指定时间返回-1 相等返回0
- equals(DateTime d) 比较两时间是否相等
- isAfter(long instant) 判断时间是否大于指定时间
- isAfterNow() 判断时间是否大于当前时间
- isBefore(long instant) 判断时间是否小于指定时间
- isBeforeNow() 判断时间是否小于当前时间
- isEqual(long instant) 判断时间是否等于指定时间
- isEqualNow() 判断时间是否等于当前时间
2.3.3 以Joda-Time的方式格式化时间
//传入的格式化模板只需与JDKSimpleDateFormat兼容的格式字符串即可
publicstaticStringconvert(Datedate,StringdateFormat){
returnnewDateTime(date).toString(dateFormat);
}
//将JDK中的Date转化为UTC时区的DateTime
DateTimedateTime=newDateTime(newDate(),DateTimeZone.UTC);
//将String转换为DateTime
publicstaticDateconvertUTC2Date(StringutcDate){
DateTimedateTime=DateTime.parse(utcDate,DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
returndateTime.toDate();
}
更多使用方法请参考官方文档。
三、JAVA 8中新的时间类库
3.1 简介
由于JDK之前版本的类库的缺陷和糟糕的使用体验,再加上已经成为事实标准Joda-Time的影响力,Oracle决定在JAVA API中提供高质量的日期和时间支持,这也就是整合了大部分Joda-Time特性的JDK 8新的时间类库。(Joda-Time的作者实际参与开发,并且实现了JSR310的全部内容,新的API位于java.time下。常用的类有以下几个:LocalDate、LocalTime、Instant、Duration和Period。)
由于JDK 8 新的时间类库大量借鉴了Joda-Time的设计思想乃至命名,因此如果你是Joda-Time的使用者,那你可以无学习成本的使用新的API(当然,它们之间也存在些许差别需要注意到)。
3.2 使用方法
3.2.1 使用LocalDate 和LocalTime
首先是LocalDate,该类的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息。另外,它也不附带任何与时区相关的信息。
//使用指定的日期创建LocalDate
LocalDatedate=LocalDate.of(2019,1,1);
//获取当前日期
LocalDatetoday=LocalDate.now();
//获取今日的属性
intyear=date.getYear();
Monthmonth=date.getMonth();
intday=date.getDayOfMonth();
DayOfWeekdow=date.getDayOfWeek();
intlen=date.lengthOfMonth();
booleanleap=date.isLeapYear();
//通过ChronoField的枚举值获取需要的属性字段
intyear=date.get(ChronoField.YEAR);
接着是LocalTime,它表示了一天内的某个时刻。
LocalTimetime=LocalTime.of(18,18,18);
inthour=time.getHour();
intminute=time.getMinute();
intsecond=time.getSecond();
LocalDate和LocalTime都可以通过使用静态方法parse来解析字符串进行创建。
LocalDatedate=LocalDate.parse("2019-01-01");
LocalTimetime=LocalTime.parse("18:18:18");
也可以向parse方法传递一个DateTimeFormatter,该类的实例定义了如何格式化一个日期或者时间对象。它其实是老版java.util.DateFormat的替代品。
3.2.2 LocalDateTime
//直接创建LocalDateTime
LocalDateTimedt1=LocalDateTime.of(2019,Month.JANUARY,1,18,18,18);
//合并日期和时间
LocalDatedate=LocalDate.parse("2019-01-01");
LocalTimetime=LocalTime.parse("18:18:18");
LocalDateTimedt2=LocalDateTime.of(date,time);
LocalDateTimedt3=date.atTime(18,18,18);
LocalDateTimedt4=date.atTime(time);
LocalDateTimedt5=time.atDate(date);
//从LocalDateTime中提取LocalDate或者LocalTime
LocalDatedate1=dt1.toLocalDate();
LocalTimetime1=dt1.toLocalTime();
3.3.3 Instant
Instant类是为了方便计算机理解的而设计的,它表示一个持续时间段上某个点的单一大整型数,实际上它是以Unix元年时间(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的秒数进行计算(最小计算单位为纳秒)。
//传递一个秒数已创建该类的实例
Instant.ofEpochSecond(3);
//传递一个秒数+纳秒2秒之后再加上100万纳秒(1秒)
Instant.ofEpochSecond(2,1_000_000_000);
3.3.4 Duration与Period
Duration是用于比较两个LocalTime对象或者两个Instant之间的时间差值。
Durationd1=Duration.between(time1,time2);
Durationd1=Duration.between(dateTime1,dateTime2);
Durationd2=Duration.between(instant1,instant2);
Period是用于对年月日的方式对多个时间进行比较。
PeriodtenDays=Period.between(LocalDate.of(2019,1,1),lcalDate.of(2019,2,2));
当然,Duration和Period类都提供了很多非常方便的工厂类,直接创建对应的实例。
DurationthreeMinutes=Duration.ofMinutes(3);
DurationthreeMinutes=Duration.of(3,ChronoUnit.MINUTES);
PeriodtenDays=Period.ofDays(10);
PeriodthreeWeeks=Period.ofWeeks(3);
PeriodtwoYearsSixMonthsOneDay=Period.of(2,6,1);
3.3.5 操作、解析和格式化日期
//直接使用withAttribute的方法修改
LocalDatedate1=LocalDate.of(2019,1,1);
LocalDatedate2=date1.withYear(2019);
LocalDatedate3=date2.withDayOfMonth(1);
LocalDatedate4=date3.with(ChronoField.MONTH_OF_YEAR,1);
所有声明了Temporal接口的类LocalDate、LocalTime、LocalDateTime以及Instant,它们都使用get和with方法,将对象值的读取和修改区分开,如果使用了不支持的字段访问字段,会抛出一个UnsupportedTemporalTypeException异常。类似的,plus方法和minus方法都声明于Temporal接口。通过这些方法,对TemporalUnit对象加上或者减去一个数字,我们能非常方便地将Temporal对象前溯或者回滚至某个时间段,通过ChronoUnit枚举我们可以非常方便地实现TemporalUnit接口。
3.3.6 更多定制化的处理时间
向重载的with方法传递一个定制化的TemporalAdjuster对象,可以更加灵活地处理日期。时间和日期的API已经提供了大量预定义的TemporalAdjuster,可以通过TemporalAdjuster类的静态工厂方法访问它们。这些方法的名称非常直观,方法名就是问题描述。某些情况下,如果你需要定义自己的TemporalAdjuster,只需要声明TemporalAdjuster接口并且自己实现对应的方法即可。
LocalDatedate1=LocalDate.of(2014,3,18);
LocalDatedate2=date1.with(TemporalAdjuster.nextOrSame(DayOfWeek.SUNDAY));
LocalDatedate3=date2.with(TemporalAdjuster.lastDayOfMonth());
3.3.7 解析日期-时间对象
日常工作中,格式化以及解析日期-时间对象是另一个非常重要的功能,而新的java.time.format包就是特别为我们达到这个目的而设计的。这其中,最重要的类是DateTimeFormatter。所有的DateTimeFormatter实例都能用于以一定的格式创建代表特定日期或时间的字符串。(与老的java.util.DateFormat相比较,所有的DateTimeFormatter实例都是线程安全的)
//使用不同的格式器生成字符串
LocalDatedate=LocalDate.of(2019,1,1);
Strings1=date.format(DateTimeFormatter.BASIC_ISO_DATE);
Strings2=date.format(DateTimeFormatter.ISO_LOCAL_DATE);
//生成LocalDate对象
LocalDatedate1=LocalDate.parse("20190101",DateTimeFormatter.BASIC_ISO_DATE);
LocalDatedate2=LocalDate.parse("2019-01-01",DateTimeFormatter.ISO_LOCAL_DATE);
//使用特定的模式创建格式器
DateTimeFormatterformatter=DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDatedate1=LocalDate.of(2019,1,1);
StringformattedDate=date1.format(formatter);
LocalDatedate2=LocalDate.parse(formattedDate,formatter);
3.3.8 处理不同的时区和日历系统
在新的日期-时间类库中,为了最大程度上的减少在处理时区带来的繁琐和复杂而使用了新的java.time.ZoneId类(与其他日期和时间类一样,ZoneId类也是无法修改的) 来替代老版的java.util.TimeZone。时区是按照一定的规则将区域划分成标准时间相同的区间。在ZoneRules这个类中包含了40个这样的实例。可以简单地通过调用ZoneId的getRules()得到指定时区的规则。每个特定的ZoneId对象都由一个地区ID标识,地区ID都为“{区域}/{城市}”的格式。比如:
ZoneIdromeZone=ZoneId.of("Asia/Shanghai");
Java 8中在原先的TimeZone中加入了新的方法toZoneId,其作用是将一个老的时区对象转换为ZoneId:
ZoneIdzoneId=TimeZone.getDefault().toZoneId();
得到的ZoneId对象后可以将它与LocalDate、LocalDateTime或者是Instant对象整合起来,构造为一个ZonedDateTime实例,它代表了相对于指定时区的时间点:
LocalDatedate=LocalDate.of(2019,Month.JANUARY,1);
ZonedDateTimezdt1=date.atStartOfDay(romeZone);
LocalDateTimedateTime=LocalDateTime.of(2019,Month.JANUARY,18,13,45);
ZonedDateTimezdt2=dateTime.atZone(romeZone);
Instantinstant=Instant.now();
ZonedDateTimezdt3=instant.atZone(romeZone);
通过ZoneId,还可以将LocalDateTime转换为Instant:
LocalDateTimedateTime=LocalDateTime.of(2019,Month.JANUARY,18,13,45);
InstantinstantFromDateTime=dateTime.toInstant(romeZone);
同样可以通过反向的方式得到LocalDateTime对象:
Instantinstant=Instant.now();
LocalDateTimetimeFromInstant=LocalDateTime.ofInstant(instant,romeZone);
与Joda-Time所不同的是,Java8中的日期-时间类库提供了4种其他的日历系统,这些日历系统中的每一个都有一个对应的日志类,分别是ThaiBuddhistDate、MinguoDate 、JapaneseDate 以及HijrahDate 。所有这些类以及LocalDate 都实现了ChronoLocalDate接口,能够对公历的日期进行建模。利用LocalDate对象,你可以创建这些类的实例。同样的,利用它们提供的静态工厂方法,你可以创建任何一个Temporal对象的实例。
LocalDatedate=LocalDate.of(2019,Month.JANUARY,1);
JapaneseDatejapaneseDate=JapaneseDate.from(date);
参考资料
Joda-Time 简介 Joda Time项目和java8时间api
动态计算时间段
需求:如现在是13:00,则时间段为15:10-17:10、17:10-19:10、19:10-21:10;即最早的出发时间为当前时间+参数【2h10min】,最迟的时间段为开始时间在20点前结束时间在20点后的时间段),求解共有多少个时间段?
分析:
- 第一个时间段的开始时间:当前时间+参数【2h10min】,中间的时间段是2h;
- 通过理解这句:最迟的时间段为开始时间在20点前结束时间在20点后的时间段,我们可以假设最大的时间变量为 max
- 假设当前时间为now,总共有n个时间段,可以推导出公式:now + (2h * n) + 10min <= max;
注意:计算过程都转换成毫秒
publicclassTest{
//毫秒
staticfinallongslot=130*60*1000;
privatestaticList<TimeSelectItem>buildStartEndTime(Longnow,Longmax){
//now+(2h*n)+10min<=max;
Longn=(max-now-60*1000)/(120*60*1000);
System.out.println("max:"+max);
System.out.println("now:"+now);
System.out.println("max-now:"+(max-now));
System.out.println("n:"+n);
List<TimeSelectItem>timeSelectItems=newArrayList<>();
LongstartTimestamp=now+slot;
LongendTimestamp=startTimestamp+120*60*1000;
for(inti=1;i<=n;i++){
//起始时间
//startTimestamp=startTimestamp+i*(120*60*1000);
//结束时间
endTimestamp=startTimestamp+(120*60*1000);
System.out.println(startTimestamp);
System.out.println(endTimestamp);
TimeSelectItemitem=newTimeSelectItem();
DateTimedt=newDateTime(startTimestamp);
inthour=dt.hourOfDay().get();
intmillis=dt.getMinuteOfHour();
StringstartTag=hour+":"+millis;
DateTimedt1=newDateTime(endTimestamp);
inthour1=dt1.hourOfDay().get();
longmillis1=dt1.getMinuteOfHour();
StringenTag=hour1+":"+millis1;
item.setDisplayName(startTag+"-"+enTag);
item.setStartTimestamp(startTimestamp);
item.setEndTimestamp(endTimestamp);
timeSelectItems.add(item);
startTimestamp=endTimestamp;
}
returntimeSelectItems;
}
publicstaticvoidmain(String[]args){
Longstart=DateTime.now().getMillis();
Calendarc=Calendar.getInstance();
c.setTime(newDate());
c.set(Calendar.HOUR_OF_DAY,20);
c.set(Calendar.MINUTE,0);
c.set(Calendar.SECOND,0);
DateTimedt=newDateTime();
dt.withHourOfDay(20);
Longend=c.getTimeInMillis();
//List<TimeSelectItem>list=buildStartEndTime(1614747600000L,1614772800000L);
List<TimeSelectItem>list=buildStartEndTime(1614834000000L,end);
for(TimeSelectItemitem:list){
System.out.println(item);
}
}
}
推荐阅读
-
江苏取消少数民族考生中考加分政策,教育公平如何实现?
1.为什么江苏取消少数民族考生中考加分政策?江苏取消少数民族考生中考加分政策的原因是为了保证教育公平。少数民族加分政策在一定程度...
-
半球电压力锅不加热了,教你如何快速解决问题
1.检查电源首先,我们需要检查电压力锅的电源是否正常。可以尝试将电压力锅插到其他插座中,或者使用其他电器测试该插座是否正常。如果...
-
空调外机多重最好(空调外机的重量标准)
-
地线颜色一般是什么颜色(接地线颜色的规范要求)
-
洗碗机必须用洗碗盐吗?专家为你介绍洗碗机的正确使用方法
在使用洗碗机的时候,我们经常会听到洗碗机需要用洗碗盐来进行清洁,但是很多人并不知道洗碗盐的作用和正确使用方法。本文将为大家介绍洗碗...
-
卫生间地面漏水维修多少钱(修补卫生间漏水费用)
-
环氧地坪多少钱(环氧树脂地坪价格)
-
空调发出咕噜咕噜水声怎么消除(空调下雨天咕噜咕噜响解决方法)
-
砂浆是什么东西(砂浆组成详情)
-
集装箱体积计算方法(箱量快速计算的公式)