侧边栏壁纸
  • 累计撰写 781 篇文章
  • 累计创建 1 个标签
  • 累计收到 1 条评论
标签搜索

时间

Dettan
2021-04-10 / 0 评论 / 0 点赞 / 107 阅读 / 10,716 字
温馨提示:
本文最后更新于 2022-04-30,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
前后端传输Date类型数据时格式化日期_dxyzhbb的博客-CSDN博客
问题一: 后台在返回json格式的Date类型数据时,直接通过@ResponseBody返回出去的是一个长整型时间戳: 解决方法: @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 它的作用是,出参时,自动把Date型对象数据转化成格式化后的字符串输出: yyyy-MM-dd HH:mm:ss 案例: timezone是用于调整时区的属性(东八区),不加的话得到的时间会比实际的少8个小时 Postman请求结果: 问题二: 前端以字符串的形式给后台传递 带有格式的 日期 和 数字 数据,导致后台无法解析数据: 解决方法: 总结: 1.如果前后端传的数据都是json格式,那么后台接数据,传数据都可以用@JsonFormat ; 2.@DateTimeFormat适合后端接收前端传来的数据,不管是不是json格式都可以正确转换成Date型数据,只要前端传来的格式正确且后端@DateTimeFormat的pattern写正确。但是,这个注解无法将Date型数据用json传到前端去 解决spring boot接收前端传递过来的json数据时,接收到的时间与实际传递时间不一致的问题 spring boot接收前端传递过来的时间,总是比实际时间晚几个小时或者早几个小时,这是由于使用在@RequestBody 实体类,进行接收json类型字符串的时候,会把接受的string时间字段转换成lang类型,然后对应实体类的时候,会按照GMT+0时区的时间进行处理。 解决办法: 1,使用@JsonFormat注解,并且指定时区 @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") private Date timingDate; 2,使用@DateTimeFormat注解,但此方法在pattern="yyyy-MM-dd HH:mm:ss"时不适用Jackson,只支持时间类型为pattern="yyyy-MM-dd"的。 @DateTimeFormat(pattern="yyyy-MM-dd") private Date timingDate; 3,Controller接收时,按照json字符串接收,然后代码对应到bean里时,特殊处理时间字段。 需要使用到net.sf.json。 import net.sf.json.JSONObject; import net.sf.json.util.JSONUtils; @RequestMapping("/insideByJson.tml") public @ResponseBody Map insideByJson(@RequestBody String jsonParam) { //json字符串转换成bean JSONObject json=JSONObject.fromObject(jsonParam); String[] dateFormats = new String[]{"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"}; JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(dateFormats)); Inside inside=(Inside) JSONObject.toBean(json, Inside.class); }
https://blog.csdn.net/dxyzhbb/article/details/100538654
这篇只有jdk-8的新的时间API , 直接用java8的时间就行了, 以前的不用记.
jdk-8 时间api是 JSR-30的实现.
设计原则
不变性:新的日期/时间 API 中,所有的类都是不可变的,这对多线程环境有好处。
关注点分离:新的 API 将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类。
清晰:在所有的类中,方法都被明确定义用以完成相同的行为。举个例子,要拿到当前实例我们可以使用 now()方法,在所有的类中都定义了 format()和 parse()方法,而不是像以前那样专门有一个独立的类。为了更好的处理问题,所有的类都使用了工厂模式和策略模式,一旦你使用了其中某个类的方法,与其他类协同工作并不困难。
实用操作:所有新的日期/时间 API 类都实现了一系列方法用以完成通用的任务,如:加、减、格式化、解析、从日期/时间中提取单独部分,等等。
可扩展性:新的日期/时间 API 是工作在 ISO-8601 日历系统上的,但我们也可以将其应用在非 ISO 的日历上

数据库类型 timeStamp 用sql的类timeStamp存, new TimeStamp(System.millils()) 就可以.

时间戳 → 时间
long millis = System.currentTimeMillis();
LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of("Asia/ShangHai"));
时间 → 时间戳
long l = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
LocalTime
isAfter()
@Test
public void testLocalTime() {
    LocalTime lt = LocalTime.now();
    System.out.println("当前时间到毫秒" + lt + ";时间" + lt.getHour() + ":" + lt.getMinute() + ":" + lt.getSecond() + "." + lt.getNano());
}
LocalDate
@Test
public void testLocalDate() {
    LocalDate ld = LocalDate.now();//等价于LocalDate.now(Clock.systemDefaultZone())
    System.out.println("日期:" + ld + ";年:" + ld.getYear() + ";月:" + ld.getMonthValue() + ";月中天:" + ld.getDayOfMonth() + "\n" +
            "年中天:" + ld.getDayOfYear() + ";周中天:" + ld.getDayOfWeek() + ";是否闰年:" + ld.isLeapYear() + ";月份天数:" + ld.lengthOfMonth() + "\n" +
            ";年天数:" + ld.lengthOfYear()
    );
    LocalDate a = LocalDate.of(2012, 7, 2);
    LocalDate b = LocalDate.of(2012, 7, 2);
    System.out.println("a在b之后吗?" + a.isAfter(b) + "\n" + "a在b之前吗?" + a.isBefore(b) + "\n" + "a和b同一天吗?" + a.isEqual(b));
}
DateTimeFormatter
所有类型的时间的 格式化 和 解析 都靠它
public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) {
    Objects.requireNonNull(formatter, "formatter");
    return formatter.parse(text, LocalDate::from);
}

@Override // override for Javadoc and performance
public String format(DateTimeFormatter formatter) {
Objects.requireNonNull(formatter, "formatter");
return formatter.format(this);
}




格式化 解析

新的日期API中提供了一个DateTimeFormatter类用于处理日期格式化操作,它被包含在java.time.format包中,Java 8的日期类有一个format()方法用于将日期格式化为字符串,该方法接收一个DateTimeFormatter类型参数:
LocalDateTime dateTime = LocalDateTime.now();
String strDate1 = dateTime.format(DateTimeFormatter.BASIC_ISO_DATE);    // 20170105
String strDate2 = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE);    // 2017-01-05
String strDate3 = dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME);    // 14:20:16.998
String strDate4 = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));   // 2017-01-05
String strDate5 = dateTime.format(DateTimeFormatter.ofPattern("今天是:YYYY年 MMMM DD日 E", Locale.CHINESE)); // 今天是:2017年 一月 05日 星期四
同样,日期类也支持将一个字符串解析成一个日期对象,例如:
String strDate6 = "2017-01-05";
String strDate7 = "2017-01-05 12:30:05";

LocalDate date = LocalDate.parse(strDate6, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDateTime dateTime1 = LocalDateTime.parse(strDate7, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));




DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");

LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);

//Format examples
LocalDate date = LocalDate.now();
//default format
System.out.println("Default format of LocalDate="+date);
//specific format
System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu")));
System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));
LocalDateTime dateTime = LocalDateTime.now();
//default format
System.out.println("Default format of LocalDateTime="+dateTime);
//specific format
System.out.println(dateTime.format(DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss")));
System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));
Instant timestamp = Instant.now();
// 默认有 格式化
System.out.println("Default format of Instant="+timestamp);
// 解析
LocalDateTime dt = LocalDateTime.parse("27::Apr::2014 21::39::48",
		DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss"));
System.out.println("Default format after parsing = "+dt);


输出:
Default format of LocalDate=2014-04-28
28::Apr::2014
20140428
Default format of LocalDateTime=2014-04-28T16:25:49.341
28::Apr::2014 16::25::49
20140428
Default format of Instant=2014-04-28T23:25:49.342Z
Default format after parsing = 2014-04-27T21:39:48
            <div style="display:flex;width:100%;font-weight:600;font-size:1.5em;line-height:1.3;color:inherit;">
                <div data-root="true" style="max-width:100%;width:100%;white-space:unset;word-break:break-word;padding:3px 2px;">

LocalDateTime 转 Date

LocalDateTime localDateTime=LocalDateTime.now()
Date date = Date.from(localDateTime.atZone( ZoneId.systemDefault()).toInstant());
Date 转 LocalDateTime
Date startDate=new Date();
LocalDateTime localDateTime = startDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime()

如何取得从1970年1月1日0时0分0 秒到现在的毫秒数?
1.
Calendar.getInstance().getTimeInMillis(); //第一种方式
2.
System.currentTimeMillis(); //第二种方式
3.
Clock.systemDefaultZone().millis();
4.
long endtime = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
Year
@Test
public void testYear() {
    Year y = Year.now();
    System.out.println("天数:" + y.length() + ";是否闰年:" + y.isLeap() + ";年份值:" + y.getValue());

}

Instant         时间戳
Duration        持续时间、时间差
LocalDate       只包含日期,比如:2018-09-24
LocalTime       只包含时间,比如:10:32:10
LocalDateTime   包含日期和时间,比如:2018-09-24 10:32:10
Peroid          时间段
ZoneOffset      时区偏移量,比如:+8:00
ZonedDateTime   带时区的日期时间
Clock           时钟,可用于获取当前时间戳
java.time.format.DateTimeFormatter      时间格式化类
            <div style="display:flex;width:100%;font-weight:600;font-size:1.5em;line-height:1.3;color:inherit;">
                <div data-root="true" style="max-width:100%;width:100%;white-space:unset;word-break:break-word;padding:3px 2px;">

如何取得某月的最后一天?

LocalDate today = LocalDate.now();  
//本月的第一天  
LocalDate firstday = LocalDate.of(today.getYear(),today.getMonth(),1);  
//本月的最后一天  
LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());  
System.out.println("本月的第一天"+firstday);  
System.out.println("本月的最后一天"+lastDay);
获取当前时间
LocalDateTime.now()
Instant
一瞬间,指一个时间点. 获取毫秒数
Duration
Duration的内部实现与Instant类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是Instant用于表示一个时间戳(或者说是一个时间点),而Duration表示一个时间段,所以Duration类中不包含now()静态方法。可以通过Duration.between()方法创建Duration对象:
LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0);    // 2017-01-05 10:07:00
LocalDateTime to = LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0);     // 2017-02-05 10:07:00
Duration duration = Duration.between(from, to);     // 表示从 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这段时间

long days = duration.toDays(); // 这段时间的总天数
long hours = duration.toHours(); // 这段时间的小时数
long minutes = duration.toMinutes(); // 这段时间的分钟数
long seconds = duration.getSeconds(); // 这段时间的秒数
long milliSeconds = duration.toMillis(); // 这段时间的毫秒数
long nanoSeconds = duration.toNanos(); // 这段时间的纳秒数



Duration对象还可以通过of()方法创建,该方法接受一个时间段长度,和一个时间单位作为参数:
Duration duration1 = Duration.of(5, ChronoUnit.DAYS);       // 5天
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS);  // 1000毫秒
Period
Period在概念上和Duration类似,区别在于Period是以年月日来衡量一个时间段,比如2年3个月6天:
Period period = Period.of(2, 3, 6);
Period对象也可以通过between()方法创建,值得注意的是,由于Period是以年月日衡量时间段,所以between()方法只能接收LocalDate类型的参数:
// 2017-01-05 到 2017-02-05 这段时间
Period period = Period.between(
                LocalDate.of(2017, 1, 5),
                LocalDate.of(2017, 2, 5));
ISO-8601日历系统中基于日期的时间量,也就是时间段. 例如“2年、3个月和4天”。
时区
Java 8中的时区操作被很大程度上简化了,新的时区类java.time.ZoneId是原有的java.util.TimeZone类的替代品。ZoneId对象可以通过ZoneId.of()方法创建,也可以通过ZoneId.systemDefault()获取系统默认时区:
ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
ZoneId systemZoneId = ZoneId.systemDefault();
of()方法接收一个“区域/城市”的字符串作为参数,你可以通过getAvailableZoneIds()方法获取所有合法的“区域/城市”字符串:
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
对于老的时区类TimeZone,Java 8也提供了转化方法:
ZoneId oldToNewZoneId = TimeZone.getDefault().toZoneId();
有了ZoneId,我们就可以将一个LocalDateLocalTimeLocalDateTime对象转化为ZonedDateTime对象:
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, shanghaiZoneId);
zonedDateTime打印到控制台为:
2017-01-05T15:26:56.147+08:00[Asia/Shanghai]
ZonedDateTime对象由两部分构成,LocalDateTimeZoneId,其中2017-01-05T15:26:56.147部分为LocalDateTime+08:00[Asia/Shanghai]部分为ZoneId
另一种表示时区的方式是使用ZoneOffset,它是以当前时间和**世界标准时间(UTC)/格林威治时间(GMT)**的偏差来计算,例如:
ZoneOffset zoneOffset = ZoneOffset.of("+09:00");
LocalDateTime localDateTime = LocalDateTime.now();
OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, zoneOffset);
其他历法
Java中使用的历法是ISO 8601日历系统,它是世界民用历法,也就是我们所说的公历。平年有365天,闰年是366天。闰年的定义是:非世纪年,能被4整除;世纪年能被400整除。为了计算的一致性,公元1年的前一年被当做公元0年,以此类推。
此外Java 8还提供了4套其他历法(很奇怪为什么没有汉族人使用的农历),每套历法都包含一个日期类,分别是:
ThaiBuddhistDate:泰国佛教历
MinguoDate:中华民国历
JapaneseDate:日本历
HijrahDate:伊斯兰历
每个日期类都继承ChronoLocalDate类,所以可以在不知道具体历法的情况下也可以操作。不过这些历法一般不常用,除非是有某些特殊需求情况下才会使用。
这些不同的历法也可以用于向公历转换:
LocalDate date = LocalDate.now();
JapaneseDate jpDate = JapaneseDate.from(date);
由于它们都继承ChronoLocalDate类,所以在不知道具体历法情况下,可以通过ChronoLocalDate类操作日期:
Chronology jpChronology = Chronology.ofLocale(Locale.JAPANESE);
ChronoLocalDate jpChronoLocalDate = jpChronology.dateNow();
我们在开发过程中应该尽量避免使用ChronoLocalDate,尽量用与历法无关的方式操作时间,因为不同的历法计算日期的方式不一样,比如开发者会在程序中做一些假设,假设一年中有12个月,如果是中国农历中包含了闰月,一年有可能是13个月,但开发者认为是12个月,多出来的一个月属于明年的。再比如假设年份是累加的,过了一年就在原来的年份上加一,但日本天皇在换代之后需要重新纪年,所以过了一年年份可能会从1开始计算。
在实际开发过程中建议使用LocalDate,包括存储、操作、业务规则的解读;除非需要将程序的输入或者输出本地化,这时可以使用ChronoLocalDate类。



0

评论区