Android-时区时间戳转换及遇到的坑

1.背景

台北时区下,用户在客户端填写生日1979/08/01,客户端将1979/08/01 00:00:00(台北时区)转化为时间戳传给后端,后端在存储时,需解析出月份并单独保存到一个字段,用于生日券发放。接口在解析时用到北京时区,解析出的时间为1979/07/31 23:00:00(北京时区),所以该用户的月份字段值为7,得到了七月份生日券。

2.修改方案

取客户选择的日期+00:00:00(0时区),将该时间转化为时间戳传给后端,这样后端转化时,不会再出现日期不一致的情况。

3.实现步骤

 		Date date = new Date(); //模拟用户填写的日期
        Calendar cd = Calendar.getInstance();
        cd.setTime(date);
        cd.setTimeZone(TimeZone.getTimeZone("UTC")); //设置时区

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        
        //获取年月日,重置时分秒
        cd.set(cd.get(Calendar.YEAR), cd.get(Calendar.MONTH), cd.get(Calendar.DATE), 0, 0, 0);
        System.out.println(simpleDateFormat.format(cd.getTimeInMillis()));  //输出2022-07-13 00:00:00
        System.out.println(cd.getTimeInMillis());  //输出1657670400490
        

4.遇到的坑

		System.out.println(simpleDateFormat.format(cd.getTimeInMillis()));  //输出2022-07-13 00:00:00
		System.out.println(cd.getTimeInMillis());  //输出1657670400490

此时转换后得到的时间戳存在毫秒级的误差 1657670400490
在这里插入图片描述
添加以下

		cd.set(Calendar.MILLISECOND, 0); //单独设置毫秒,避免误差

得到

    	System.out.println(simpleDateFormat.format(cd.getTimeInMillis())); //2022-07-13 00:00:00
    	System.out.println(cd.getTimeInMillis()); //输出1657670400000

在这里插入图片描述

5.完整代码

Java

		Date date = new Date(); //模拟用户填写的日期
        Calendar cd = Calendar.getInstance();
        cd.setTime(date);
        cd.setTimeZone(TimeZone.getTimeZone("UTC")); //设置时区

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

        //获取年月日,重置时分秒
        cd.set(cd.get(Calendar.YEAR), cd.get(Calendar.MONTH), cd.get(Calendar.DATE), 0, 0, 0);
        cd.set(Calendar.MILLISECOND, 0); //单独设置毫秒,避免误差

        System.out.println(simpleDateFormat.format(cd.getTimeInMillis())); //2022-07-13 00:00:00
        System.out.println(cd.getTimeInMillis()); //输出1657670400000

Kotlin

		val date = Date()
        val cd = Calendar.getInstance()
        cd.time = date
        cd.timeZone = TimeZone.getTimeZone("UTC")
        cd[cd[Calendar.YEAR], cd[Calendar.MONTH], cd[Calendar.DATE], 0, 0] = 0
        cd[Calendar.MILLISECOND] = 0 //单独设置,避免毫秒级的误差

6.模拟


    void testTime() {
        for (int i = 0; i < 2023; i++) {
            for (int j = 0; j < 12; j++) {
                time(i, j);
            }
        }
    }

    private void time(int year, int month) {
        Date date = new Date(); //模拟用户填写的日期 如果用电脑 就把电脑时区设置成台北 如果用手机 就设置手机时区
        Calendar cd = Calendar.getInstance();
        cd.setTime(date);
        cd.set(year, month, 1, 0, 0, 0);

        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        simpleDateFormat1.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        if (simpleDateFormat1.format(cd.getTimeInMillis()).contains("-31")){
            System.out.println(simpleDateFormat1.format(cd.getTimeInMillis()));
            System.out.println("");
        }
    }

结果
1900-01-31 23:54:17

1900-03-31 23:54:17

1900-05-31 23:54:17

1900-07-31 23:54:17

1900-08-31 23:54:17

1900-10-31 23:54:17

1919-05-31 23:00:00

1919-07-31 23:00:00

1919-08-31 23:00:00

1940-07-31 23:00:00

1940-08-31 23:00:00

1941-03-31 23:00:00

1941-05-31 23:00:00

1941-07-31 23:00:00

1941-08-31 23:00:00

1941-10-31 23:00:00

1942-01-31 23:00:00

1942-03-31 23:00:00

1942-05-31 23:00:00

1942-07-31 23:00:00

1942-08-31 23:00:00

1942-10-31 23:00:00

1942-12-31 23:00:00

1943-01-31 23:00:00

1943-03-31 23:00:00

1943-05-31 23:00:00

1943-07-31 23:00:00

1943-08-31 23:00:00

1943-10-31 23:00:00

1943-12-31 23:00:00

1944-01-31 23:00:00

1944-03-31 23:00:00

1944-05-31 23:00:00

1944-07-31 23:00:00

1944-08-31 23:00:00

1944-10-31 23:00:00

1944-12-31 23:00:00

1945-01-31 23:00:00

1945-03-31 23:00:00

1945-05-31 23:00:00

1945-07-31 23:00:00

1945-08-31 23:00:00

1946-05-31 23:00:00

1946-07-31 23:00:00

1946-08-31 23:00:00

1947-05-31 23:00:00

1947-07-31 23:00:00

1947-08-31 23:00:00

1948-05-31 23:00:00

1948-07-31 23:00:00

1948-08-31 23:00:00

1986-05-31 23:00:00

1986-07-31 23:00:00

1986-08-31 23:00:00

1987-05-31 23:00:00

1987-07-31 23:00:00

1987-08-31 23:00:00

1988-05-31 23:00:00

1988-07-31 23:00:00

1988-08-31 23:00:00

1989-05-31 23:00:00

1989-07-31 23:00:00

1989-08-31 23:00:00

1990-05-31 23:00:00

1990-07-31 23:00:00

1990-08-31 23:00:00

1991-05-31 23:00:00

1991-07-31 23:00:00

1991-08-31 23:00:00

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值