获取时间和格式化时间,延时函数使用

参考资料:

1.https://blog.csdn.net/u011212112/article/details/90478610

2.https://blog.csdn.net/qq_36761831/article/details/79691119

3.https://blog.csdn.net/l871243720/article/details/121801987

 

1.Date中保存的是什么?

在java中,只要我们执行

Date date = new Date();

就可以得到当前时间。如:

import java.util.Date;

public class Demo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);   // 输出当前时间
    }
}

输出结果是:

Fri Sep 30 00:10:45 CST 2022

也就是我执行上述代码的时刻:2022年9月30日00点10分45秒 周五。是不是Date对象里存了年月日时分秒呢?不是的,Date对象里存的只是一个long型的变量,其值为自1970年1月1日0点至Date对象所记录时刻经过的毫秒数,调用Date对象getTime()方法就可以返回这个毫秒数,如下代码:

import java.util.Date;

public class Demo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date.getTime());   // 输出当前毫秒数
    }
}

输出如下:

1664470419695

即上述程序执行的时刻距离1970年1月1日0点有1664470419695毫秒。

2.时区

(代码种有关SimpleDateFormat的详细说明参考后续5)

全球分为24个时区,相邻时区时间相差1个小时。比如北京处于东八时区,东京处于东九时区,北京时间比东京时间晚1个小时。比如此刻北京时间是2022年9月30日00点10分45秒,则东京时间是2022年9月30日01点10分45秒。

既然Date里存放的是当前时刻距1970年1月1日0点时刻的毫秒数,如果此刻在北京、东京有2个程序员同时执行如下语句:

Date date = new Date();

那这2个date对象里存的毫秒数是相同的吗?还是北京的比东京的小3600000(北京时间比东京时间晚1小时,1小时为3600秒即3600000毫秒)?答案是,这2个Date里的毫秒数是完全一样的。确切的说,Date对象里存的是自格林威治时间( GMT)1970年1月1日0点至Date对象所表示时刻所经过的毫秒数。所以,如果某一时刻遍布于世界各地的程序员同时执行new Date语句,这些Date对象所存的毫秒数是完全一样的。也就是说,Date里存放的毫秒数是与时区无关的。

继续上述例子,如果上述2个程序员调用那一刻的时间是北京时间2022年9月30日00点10分45秒,他们继续调用

System.out.println(date);

那么北京的程序员将会打印出2022年9月30日00点10分45秒,而东京的程序员会打印出2022年9月30日01点10分45秒。既然Date对象只存了一个毫秒数,为什么这3个毫秒数完全相同的Date对象,可以打印出不同的时间呢?这是因为Sysytem.out.println函数在打印时间时,会取操作系统当前所设置的时区,然后根据这个时区将同毫秒数解释成该时区的时间。当然我们也可以手动设置时区,以将同一个Date对象按不同的时区输出。可以做如下实验验证:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static void main(String[] args) {
        Date date = new Date();  // 获取当前程序执行时距离自格林威治时间( GMT)1970年1月1日0点所经过的毫秒数

        SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     // 北京
        bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));  // 设置北京时区

        SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 东京
        tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 设置东京时区

        System.out.println("毫秒数:" + date.getTime() + ", 北京时间:" + bjSdf.format(date));
        System.out.println("毫秒数:" + date.getTime() + ", 东京时间:" + tokyoSdf.format(date));
    }
}

输出结果是:

毫秒数:1664471019469, 北京时间:2022-09-30 01:03:39

毫秒数:1664471019469, 东京时间:2022-09-30 02:03:39

可以看出,同一个Date对象,按不同的时区来格式化,将得到不同时区的时间。

如何获取当前程序所在时区(默认时区)呢?

使用TimeZone timeZone = TimeZone.getDefault();就可以获取到程序当前运行所在的时区

示例如下:

import java.util.TimeZone;

public class Demo {
    public static void main(String[] args){
        TimeZone timeZone = TimeZone.getDefault();
        System.out.println(timeZone.getDisplayName());
        System.out.println(timeZone.getID());
    }
}

运行结果如下:

中国标准时间

Asia/Shanghai

获取默认时区后进行时区设置

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);   // 默认输出
        
        SimpleDateFormat format = new SimpleDateFormat("EE M d HH:mm:ss z yyyy");
        TimeZone timeZone = TimeZone.getDefault();  // 初始化

        System.out.println(timeZone.getID());
        format.setTimeZone(TimeZone.getTimeZone(timeZone.getID())); // 设置时区:程序所在时区
        System.out.println(format.format(date));

        format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置时区:Asia/Shanghai
        System.out.println(format.format(date));   // 输出时间
    }
}

运行结果如下:

Sat Oct 01 11:01:31 CST 2022

Asia/Shanghai

星期六 10 1 11:01:31 CST 2022

星期六 10 1 11:01:31 CST 2022

从结果可以看出,System.out.println(date);  的时区与默认时区相同;默认时区与Asia/Shanghai相同,因为当前程序在中国运行。

3.从字符串中读取时间

(代码种有关SimpleDateFormat的详细说明参考后续5)

有时我们会遇到从一个字符串中读取时间的要求,即从字符串中解析时间并得到一个Date对象,比如将"2022-9-30 01:17:10""解析为一个Date对象。现在问题来了,这个时间到底指的是北京时间的2022-9-30 01:17:10",还是东京时间的2022-9-30 01:17:10"?如果指的是北京时间,那么这个时间对应的东京时间2022-9-30 02:17:10";如果指的是东京时间,那么这个时间对应的北京时间就是2022-9-30 00:17:10"。因此,只说年月日时分秒而不说是哪个时区的,是有歧义的,没有歧义的做法是,给出一个时间字符串,同时指明这是哪个时区的时间。

从字符串中解析时间的正确作法是:指定时区来解析。示例如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static void main(String[] args) throws ParseException {
        String timeStr = "2022-9-30 01:17:10"; // 字面时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置北京时区
        Date d = sdf.parse(timeStr);
        System.out.println(sdf.format(d) + ", " + d.getTime());
    }
}

输出为:

2022-09-30 01:17:10, 1664471830000

将一个时间字符串按不同时区来解释,得到的Date对象的值是不同的。验证如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static void main(String[] args) throws ParseException {
        String timeStr = "2022-9-30 01:17:10"; // 字面时间
        SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        Date bjDate = bjSdf.parse(timeStr);  // 解析
        System.out.println("字面时间: " + timeStr + ",按北京时间来解释:" + bjSdf.format(bjDate) + ", " + bjDate.getTime());

        SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 东京
        tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 设置东京时区
        Date tokyoDate = tokyoSdf.parse(timeStr); // 解析
        System.out.println("字面时间: " + timeStr + ",按东京时间来解释:" + tokyoSdf.format(tokyoDate) + ", " + tokyoDate.getTime());
    }
}

输出为:

字面时间: 2022-9-30 01:17:10,按北京时间来解释:2022-09-30 01:17:10, 1664471830000

字面时间: 2022-9-30 01:17:10,按东京时间来解释:2022-09-30 01:17:10, 1664468230000

可以看出,对于"2022-9-30 01:17:10"这个字符串,按北京时间来解释得到Date对象的毫秒数是

1664471830000;而按东京时间来解释得到的毫秒数是1664468230000,前者正好比后者大于3600000毫秒即1个小时,正好是北京时间和东京时间的时差。

4.将字符串表示的时间转换成另一个时区的时间字符串

(代码种有关SimpleDateFormat的详细说明参考后续5)

综合以上分析,如果给定一个时间字符串,并告诉你这是某个时区的时间,要将它转换为另一个时区的时间并输出,正确的做法是:

1.将字符串按原时区转换成Date对象;

2.将Date对象格式化成目标时区的时间。

比如,将北京时间"2022-9-30 01:17:10"输出成东京时间,代码为:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static void main(String[] args) throws ParseException {
        String timeStr = "2022-9-30 01:17:10"; // 字面时间
        SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        Date date = bjSdf.parse(timeStr);  // 将字符串时间按北京时间解析成Date对象

        SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 东京
        tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 设置东京时区
        System.out.println("北京时间: " + timeStr + "对应的东京时间为:" + tokyoSdf.format(date));
    }
}

输出为:

北京时间: 2022-9-30 01:17:10对应的东京时间为:2022-09-30 02:17:10

5.SimpleDateFormat 格式化日期

包含在Java的 java.text.SimpleDateFormat;包中

日期和时间格式由 日期和时间模式字符串 指定。在 日期和时间模式字符串 中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' 被解释为模式字母,用来表示日期或时间字符串元素。文本可以使用单引号 (') 引起来,以免进行解释。所有其他字符均不解释;只是在格式化时将它们简单复制到输出字符串

白话文的讲:这些A——Z,a——z这些字母(不被单引号包围的)会被特殊处理替换为对应的日期时间,其他的字符串还是原样输出。

日期和时间模式(注意大小写,代表的含义是不同的)

yyyy:年

MM:月

dd:日

hh:1~12小时制(1-12)

HH:24小时制(0-23)

mm:分

ss:秒

S:毫秒

E:星期几

D:一年中的第几天

F:一月中的第几个星期(会把这个月总共过的天数除以7)

w:一年中的第几个星期

W:一月中的第几星期(会根据实际情况来算)

a:上下午标识

k:和HH差不多,表示一天24小时制(1-24)。

K:和hh差不多,表示一天12小时制(0-11)。

z:表示时区 

简单验证代码如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws ParseException {
        Date ss = new Date();
        System.out.println("一般日期输出:" + ss);
        System.out.println("时间戳:" + ss.getTime());
        SimpleDateFormat format0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = format0.format(ss.getTime());//这个就是把时间戳经过处理得到期望格式的时间
        System.out.println("格式化结果0:" + time);
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
        time = format1.format(ss.getTime());
        System.out.println("格式化结果1:" + time);
    }
}

运行结果:

一般日期输出:Fri Sep 30 01:32:47 CST 2022

时间戳:1664472767341

格式化结果0:2022-09-30 01:32:47

格式化结果1:2022年09月30日01时32分47秒

上面的日期和时间模式  是按我们常用的年月日时分秒来放的,下面是专业的图,供参考。

定义了以下模式字母(所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留):

一个月中的第几个星期,  F   这个出来的结果,不靠谱,后面的那个  W  靠谱。

测试程序如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static void main(String[] args) throws ParseException {
        int year = 2022;    // 可自行修改年月
        int month = 9;
        int daySum = 30; // 一个月的总天数
        System.out.print(year + "年" + month + "月\nF:一月中的第几个星期(会把这个月总共过的天数除以7)\n");
        for (int i = 1; i <= daySum; i++) {
            String timeStr = year + "-" + month + "-" + i + " 01:17:10"; // 字面时间
            SimpleDateFormat format0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            format0.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            Date date = format0.parse(timeStr);  // 将字符串时间按北京时间解析成Date对象

            SimpleDateFormat F = new SimpleDateFormat("F");
            F.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            System.out.print(F.format(date));
        }

        System.out.print("\nW:一月中的第几星期(会根据实际情况来算)\n");
        for (int i = 1; i <= daySum; i++) {
            String timeStr = year + "-" + month + "-" + i + " 01:17:10"; // 字面时间
            SimpleDateFormat format0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            format0.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            Date date = format0.parse(timeStr);  // 将字符串时间按北京时间解析成Date对象

            SimpleDateFormat W = new SimpleDateFormat("W");
            W.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            System.out.print(W.format(date));
        }

    }
}

运行结果:

2022年9月

F:一月中的第几个星期(会把这个月总共过的天数除以7)

111111122222223333333444444455

W:一月中的第几星期(会根据实际情况来算)

111222222233333334444444555555

日历截图如下:

6.延时函数使用

在Java中有时候需要使程序暂停一点时间,称为延时。普通延时用Thread.sleep(int)方法,这很简单。把它将当前线程挂起指定的毫秒数。如

try

{

Thread.sleep(1000);//单位:毫秒

} catch (Exception e) {

}

注意:Thread.sleep(int)不能直接用,要做异常处理,try{}catch{}.

sleep()方法并不能够让程序"严格"的沉睡指定的时间。例如当使用5000作为sleep()方法的参数时,线程可能在实际被挂起5000.001毫秒后才会继续运行。当然,对于一般的应用程序来说,sleep()方法对时间控制的精度足够了。

import java.util.Date;

public class Demo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);

        try {
            Thread.sleep(2000);//单位:毫秒
        } catch (Exception e) {
            System.out.println("延时异常");
        }

        date = new Date();
        System.out.println(date);
    }
}

运行结果:

Sat Oct 01 12:58:04 CST 2022

Sat Oct 01 12:58:06 CST 2022

从结果中可以看出两次输出时间差2秒。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值