同福

Java的日期和时间的使用技巧【20210408】

介绍

介绍

今天福哥将要给大家讲解Java编程基础知识日期和时间的使用技巧,这个技术在程序开发时候的使用率还是非常高的,基本上95%以上的项目都离不开日期和时间的应用场景。

关于日期和时间还是有很多知识需要了解的,如果不清楚这些的话,就会遇到很多奇怪的问题。在很多对时间控制很严格的系统里面会有非常复杂的时间处理逻辑,如果没有很好的使用经验甚至功能都无法实现。例如:昨天是什么日子?距离下一个周末还有几天?今年有多少个工作日?想要解决这些问题还是需要好好学习一下日期和时间的使用技巧的。

时区

时区时间

地球是圆的,处于不同经度地区的人看到的时间是不一样的,在一条经度上的人看到的时间是一样的。所以我们在描述一个时间的时候都会以当地经度上的一个主要城市为准计算当地的时间,例如:北京时间,东京时间,伦敦时间,纽约时间等等。

处于不同经度地区的人看到的时间之间是有差的,这个差就是我们常说的时差。服务器也是存在于某一个经度地区的,所以跨时区操作网站的时候就会有时差问题。

为了解决这个问题程序默认会以一个公共时区UTC的时间为基准,大家都以这个UTC时区的时间记录具体时间,在显示的时候可以根据所在时区与UTC时区的偏移经度计算时差,从而得到本地时区正确的具体时间。

当前时间

UTC时间

前面介绍时区的时候说过了,为了便于针对不同经度地区的人显示当地的时间系统里面存储的最好是UTC时间。

通过Calendar得到当前时间,通过SimpleDateFormat格式化输出时间,这里面设置时区是给SimpleDateFormat设置才有用,给SimpleDateFormat和Calendar都设置也行,只给Calendar设置是没用的。

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

out += "<h3>当前UTC时间</h3>";
out += simpleDateFormat.format(Calendar.getInstance().getTime());

本地时间

如果要得到对应本地时区的时间只需要去掉设置时区的代码就可以了,因为默认情况下会使用本地时区时间。

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

out += "<h3>本地时间</h3>";
out += simpleDateFormat.format(Calendar.getInstance().getTime());

创建时间

如果我们要创建一个时间(或者说是指定一个具体的时间)需要用到Calendar对象的set方法。

Calendar对象的set方法可以顺序传入年、月、日、时、分、秒的定制参数,用来构造一个特定时间。需要注意的是月份参数是从0开始计算的,也就是说“1”代表2月,“0”才是1月。

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

out += "<h3>创建时间</h3>";
Calendar calendar = Calendar.getInstance();
calendar.set(2021, 3, 8, 21, 56, 38);
out += simpleDateFormat.format(calendar.getTime());

时间偏移

时间偏移就是根据当前时间向前(过去)或者向后(未来)进行推移得到一个过去时间或者未来时间。

时间偏移是通过Calendar对象的add方法实现的,两个参数,一个是单位,一个是数量,非常好理解。

偏移单位

Calendar对象的add方法的偏移单位有很多,福哥摘抄了一部分给大家参考。

  • 1:年

  • 2:月

  • 3:周

  • 5:天

  • 11:时

  • 12:分

  • 13:秒

  • 14:微秒

未来

将当前时间向后偏移可以计算未来的某个时间点。

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar;

out += "<h3>明天</h3>";
calendar = Calendar.getInstance();
calendar.add(5, 1);
out += simpleDateFormat.format(calendar.getTime());
out += "<h3>下周的今天</h3>";
calendar = Calendar.getInstance();
calendar.add(5, 7);
out += simpleDateFormat.format(calendar.getTime());

simpleDateFormat = new SimpleDateFormat("u");
calendar = Calendar.getInstance();
out += "<h3>距离最近的周日还有" + String.valueOf(7-Integer.parseInt(simpleDateFormat.format(calendar.getTime()))) + "天</h3>";
simpleDateFormat = new SimpleDateFormat("u");
calendar = Calendar.getInstance();
calendar.add(5, 30);
out += "<h3>下个月的今天是周" + simpleDateFormat.format(calendar.getTime()) + "</h3>";

home/topic/2021/0408/23/ab56e94717742335465679c84261135f.jpg

过去

将当前时间向前偏移可以计算未来的某个时间点。

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar;

out += "<h3>昨天</h3>";
calendar = Calendar.getInstance();
calendar.add(5, -1);
out += simpleDateFormat.format(calendar.getTime());
out += "<h3>上周的今天</h3>";
calendar = Calendar.getInstance();
calendar.add(5, -7);
out += simpleDateFormat.format(calendar.getTime());

simpleDateFormat = new SimpleDateFormat("u");
calendar = Calendar.getInstance();
calendar.set(2021, 7, 8, 0, 0, 0);
calendar.add(1, -1);
out += "<h3>8月8日出生的人去年的生日那天是周" + simpleDateFormat.format(calendar.getTime()) + "</h3>";
simpleDateFormat = new SimpleDateFormat("u");
calendar = Calendar.getInstance();
calendar.set(2021, 7, 8, 0, 0, 0);
calendar.add(1, -1);
out += "<h3>8月8日出生的人自上次生日到今天过了" + Long.valueOf((Calendar.getInstance().getTime().getTime()-calendar.getTime().getTime())/(3600*24*1000)) + "天</h3>";

home/topic/2021/0408/23/cdcea1cdd60379eaa859da31dcf3fe80.jpg

格式化

在我们将系统时间输出出来的时候可以通过SimpleDateFormat提供的一些字符进行格式的自定义,下面是福哥从官网找出来的格式说明,大家可以参考看看。

格式

  • G:Era designator

  • y:Year

  • Y:Week year

  • M:Month in year

  • w:Week in year

  • W:Week in month

  • D:Day in year

  • d:Day in month

  • F:Day of week in month

  • E:Day name in week

  • u:Day number of week (1 = Monday, ..., 7 = Sunday)

  • a:Am/pm marker

  • H:Hour in day (0-23)

  • k:Hour in day (1-24)

  • K:Hour in am/pm (0-11)

  • h:Hour in am/pm (1-12)

  • m:Minute in hour

  • s:Second in minute

  • S:Millisecond

  • z:Time zone

  • Z:Time zone

  • X:Time zone

UTC时间转本地时间

时区转换过程就是拿到当前时区时间的Date对象,然后在SimpleDateFormat里面设置目标时区,再通过SimpleDateFormat输出格式化后的时间即可。

如果源时间是字符串格式,可以通过SimpleDateFormat的parse方法进行解析得到时间的Date对象。注意源时间字符串的格式要和SimpleDateFormat的格式匹配。

时区转换

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String nowUTC;

out += "<h3>UTC时间</h3>";
nowUTC = simpleDateFormat.format(Calendar.getInstance().getTime());
out += nowUTC;
out += "<h3>通过UTC时间转换为本地时间</h3>";
try {
    Date dateNowUTC = simpleDateFormat.parse(nowUTC);
    simpleDateFormat.setTimeZone(TimeZone.getDefault());
    out += simpleDateFormat.format(dateNowUTC);
}
catch (ParseException e){
    e.printStackTrace();
}

home/topic/2021/0408/23/26ee7ebe15045c9df9e0e560c3711d5e.jpg

格式转换

Java有几种时间的对象,包括Calendar、Date、Timestamp以及字符串类型。这几种时间的对象之间是如何转换的呢?

Calendar -> Date

通过Calendar.getTime可以得到Date对象。

Date date = calendar.getTime();

Date -> Timestamp

通过将Date.getTime作为构造器参数可以得到Timestamp对象。

Timestamp timestamp = new Timestamp(date.getTime());

Timestamp -> String

通过SimpleDateFormat的format方法可以得到String对象

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String datetime = simpleDateFormat.format(timestamp);

String -> Calendar

通过Calendar.setTime可以得到Calendar对象,而SimpleDateFormat的parse方法可以将String对象转换成Date对象

try {
    date = simpleDateFormat.parse(datetime);
    calendar.setTime(date);
}
catch (ParseException e){
    e.printStackTrace();
}

总结

今天福哥带着童鞋们对于Java操作日期和时间的技巧系统地学习了一下,相信经过今天的课程之后童鞋们对于在程序里面使用日期和时间的功能会变得得心应手了。

下一课福哥会给大家讲解JavaScript语言的日期和时间的使用技巧。JavaScript更想是简化版本的Java,只不过它只有一个对象就是Date,所有的日期和时间都是从这个对象开始的。