Java时间类浅析

Java关于时间的类有Date, Calendar, TimeZone和DateFormat,Date类表示时间的格式;Calendar类实现了对时间的处理;TimeZone是时区类,表示各个地区不同的时间规定(夏令时等);DateFormat类用于格式化时间的显示。

夏令时和冬令时

在一些实施了夏令时的国家,夏天从4月份开始至9月份,时间将快一个小时,而冬季则将时间拨回。也就是说夏令时区间,第一天比标准时间少1个小时,到夏令时结束时,第一天比标准时间多1个小时。我国以前有一段时间实行过夏令时,但由于人民难以掌握夏令时的计算方法,出现了不少问题,后面就没有实施了。夏令时在西方国家比较常见,在东亚地区则基本上没有。
关于夏令时和冬令时,网上有一个程序[http://josh-persistence.iteye.com/blog/2230341],以美国洛杉矶的时区为例,显示自1970年至2021年的“特殊时间”。以下是代码:

public class WhatTime {
    public static void testDayTime(TimeZone timeZone) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar start = Calendar.getInstance(timeZone);
        start.setTime(new Date(0));
        System.out.println("start=" + fmt.format(start.getTime()));
        long now = Calendar.getInstance(timeZone).getTimeInMillis();
        long year = 1000l * 3600 * 24 * 365;
        long end = now + year * 5;
        System.out.println(fmt.format(new Date(end)));
        boolean find = false;
        for(long i = start.getTimeInMillis();i<end;i=start.getTimeInMillis()){
            start.add(Calendar.DATE, 1);
            if((start.getTimeInMillis()-i)%(24*3600*1000L)!=0) {
                find = true;
                System.out.println("from" + fmt.format(new Date(i))+" to "+fmt.format(start.getTime())
                +" has "+(start.getTimeInMillis() - i) + "ms " + "[" + (start.getTimeInMillis() - i) / (3600*1000L) + "hours]"
                );
            }
        }
        if(!find){
            System.out.println("Every Day is OK.");
        }
    }

    public static void main(String args[]) {
        testDayTime(TimeZone.getTimeZone("America/Los_Angeles"));
    }
}

其计算结果为:

start=1970-01-01 08:00:00
2021-12-12 19:36:36
from1970-04-26 08:00:00 to 1970-04-27 07:00:00 has 82800000ms [23hours]
from1970-10-25 07:00:00 to 1970-10-26 08:00:00 has 90000000ms [25hours]
......

Date类

目前时间都是从1970年1月1日0时0分0秒开始的,因此,new Date(0)指的就是这个时间。直接new Date()表示本机的时间。new Date(long l)表示基于millsecond来创建时间,这个millsecond是与1970-01-01 0:0:0的偏移量。

Calendar类

Calendar类处理日期的增加、提取、设置等操作。它自动地处理复杂的夏令时和冬令时。Calendar.getInstance()方法默认返回本地操作系统所设置的时区。Calendar.setTime(Date date)则可以将一个时间设置到Calendar对象里,默认是当前时间。Calendar.getTimeInMillis()将返回Calendar时间对象的millsecond偏移量。通过对millsecond偏移量进行加减(加 +/-)操作时间,再通过Calendar.getTime就可以返回操作后的时间。

TimeZone类

TimeZone类已经设定了当前全球各个时区地区的参数,调用时仅需要输入TimeZone的ID,就可以获得TimeZone对象。你可以使用以下代码将TimeZone的详细信息输出。

String id[] = TimeZone.getAvailableIDs();
for(String idx : id) {
    System.out.println(TimeZone.getTimeZone(idx));
}

输出结果如下,以Paris为例:

sun.util.calendar.ZoneInfo[**id="Europe/Paris"**,offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]] 

里面的id就是创建TimeZone所需的参数。


时间的统一处理

对于客户端,一个人在国内递交了一个表单,服务器生成了提交的时间,另一个国外的用户查询该表单的提交时间。如何让不同时区的用户看到的时间与它本地所在的时区一致呢?综合网上搜索和自己思考,我认为,可以在后台数据库在存储时间时,将时间转为GMT(格林尼治时间)进行存储。在客户端显示时,依据客户端所处的时区(地区),再调用相应的函数输出显示。
以下是转换时间的测试类:

public class DateSave {
    public static Date convertToGMT(Date date) {
        //Local Time Zone Calendar Instance
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //calendar.setTimeZone(TimeZone.getTimeZone("UTC"));       
        //return calendar.getTime();
        int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
        int dstOffset = calendar.get(Calendar.DST_OFFSET);
        calendar.add(Calendar.MILLISECOND, -(dstOffset+zoneOffset));
        return calendar.getTime();
    }

    public static Date convertGMTToLocal(Date gmtDate, String id) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        calendar.setTime(gmtDate);
        calendar.setTimeZone(TimeZone.getTimeZone(id));
        int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
        int dstOffset = calendar.get(Calendar.DST_OFFSET);
        calendar.add(Calendar.MILLISECOND, dstOffset+zoneOffset);
        return calendar.getTime();
    }

    public static Date stringToDate(String sDate , String pattern) throws ParseException {
        DateFormat df = new SimpleDateFormat(pattern);
        return df.parse(sDate);
    }

    public static String dateToString(Date date , String pattern) {
        DateFormat df = new SimpleDateFormat(pattern);
        return df.format(date);
    } 

    public static void main(String args[]) {
        String sdate = "1988-11-30 16:03:00";
        String pattern = "yyyy-MM-dd HH:mm:ss";
        try {
            Date date = stringToDate(sdate,pattern);
            date = convertToGMT(date);
            System.out.println("GMT is "+dateToString(date,pattern));
            date = convertGMTToLocal(date,"America/Los_Angeles");
            System.out.println("Local is "+dateToString(date,pattern));
        } catch (ParseException ex) {
            Logger.getLogger(DateSave.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值