zoukankan      html  css  js  c++  java
  • Android中关于日期时间与时区的使用总结

    在开发Android的过程中,出现过几次由于日期时间导致的问题,而且主要是由于时区的原因导致,所以一直想总结一下,形成一个良好的开发规范。

     
    一、Unix时间戳
     
      Unix时间戳(Unix timestamp),或称Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方法,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。Unix时间戳不仅被使用在Unix系统、类Unix系统中,也在许多其他操作系统中被广泛采用。
     
    二、关于时间标准和时区
     
      1、原子时:International Atomic Time (IAT)
     
        又称国际原子时,是一种通过原子钟得到的时间标准,原子钟是世界上已知最准确的时间测量和频率标准,原子钟在 37 亿年的误差不超过 1 秒。
     
      2、世界时:Universal Time(UT)
     
        是一种以格林尼治子夜起算的平太阳时。世界时是以地球自转为基准得到的时间尺度,其精度受到地球自转不均匀变化和极移的影响,为了解决这种影响,1955年国际天文联合会定义了UT0、UT1和UT2三个系统,他们三者之间是递进的关系,后者都是发现前者的一些度量差别,通过修正得到更均匀的时标。
     
        在格林尼治子午线上的平太阳时称为世界时(UT0),又叫格林尼治平时(GMT)。格林尼治标准时间(旧译格林尼治平均时间或格林威治标准时间,英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。自1924年2月5日开始,格林尼治天文台每隔一小时会向全世界发放调时信息。
     
      2、协调世界时:Coordinated Universal Time(UTC)
     
        又称世界标准时间、世界统一时间。是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以“秒”为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以“世界标准时间”的角度来说,UTC比GMT更精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。
     
        基本上UTC的本质强调的是比GMT更精确的世界时间标准,UTC中多一个闰秒的调整,以确保协调世界时(UTC)与格林尼治平时(GMT)相差不会超过0.9秒,并在有需要的时候在协调世界时(UTC)内加上正或负闰秒。
     
        UTC被应用在大多数的计算机以及网络标准中。
     
      3、夏令时与冬令时:Daylight Saving Time(DST)
     
        又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。自2011年3月27日开始俄罗斯永久使用夏令时,把时间拨快一小时,不再调回。
     
        简单来说,使用夏令时和冬令时即在夏季将时间拨快一个小时,等到冬季再将时间拨慢一个小时。
     
      4、CST
     
        CST同时代表澳大利亚、美国、中国、古巴四个国家的标准时间,时区分别为:
     
         澳洲中部时间,Central Standard Time (Australia) UT+9:30
         中部标准时区(北美洲),Central Standard Time (North America) UT-6:00
         北京时间,China Standard Time UT+8:00
         古巴标准时间,Cuba Standard Time UT-4:00
     
      在开发时我们需要注意不同国家的时区,并且UTC和GMT在计算机系统中使用并无明显差别,可视为等同。
     
    二、规范
     
      在实际开发中,当时间用于显示时,非特殊要求下一般使用系统默认的时区时间作为显示时间。将时间做为数据存储或传递给其他系统时(特别是跨平台调用),则最好使用标准的UTC/GMT时间(后面统称GMT),除非事先约定或标识了时间的类型。
     
    三、在Android中需要特别注意的事项
     
      1、Android中表示日期时间的类型,有Date、Calendar,他们在没有显示设置其时区时,取到的当前时间均为系统默认时区的时间,即使给定一个时间,同样是按系统默认时区来换算时间,所以说他们都是与时区相关的。
     
      2、SimpleDateFormat对象本身也是跟时区相关。
     
        当使用parse将一个字符串格式的日期转换为Date对象,或者将一个Date对象转换为字符串日期时,这个字符串日期的时区以SimpleDateFormat关联的时区为准,如果通过setTimeZone修改了时区,则这个字符串日期以修改后的时区为准。例如:
     
    // 2013-1-31 22:17:14
    Date date = new Date(1359641834000L);
    System.out.println(date);
    String dateStr = "2013-1-31 22:17:14";
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    try
    {
        // 对于已经设定为GMT时间标准的dateFormat来说,一切需要他转换的字符串日期都是GMT标准时间,转换后返回的Date由于默认遵守系统默认时区,所以转换给Date的日期需要+8(例如北京标准时区),也就是时区与标准不同导致的时差。
        Date dateTmp = dateFormat.parse(dateStr);
        System.out.println(dateTmp);
    catch (ParseException e) 
    {
        e.printStackTrace();  
    }  
    // Date还是按系统默认时区,而format格式化处来的字符串是GMT,所以要-8。
    String dateStrTmp = dateFormat.format(date);  
    System.out.println(dateStrTmp);
        输出结果为:image
      3、Calendar在不手动设置时区时,是与系统默认时区相关的。在手动修改时区后,不能使用calendar.getTime方法来直接获取Date日期,因为此时的日期与setTime时的值相同,想要正确获取修改时区后的时间,应该通过calendar的get方法。例如:
     
    Date date = new Date(1359641834000L);
    System.out.println(date);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeZone(TimeZone.getTimeZone("GMT"));  
    // 或者可以 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));  
    calendar.setTime(date);
    System.out.println(calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));
     
    Calendar calendar2 = Calendar.getInstance();  
    calendar2.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
     
    System.out.println(calendar.getTime());  
    System.out.println(calendar2.getTime());
        输入结果为:image
     
      4、TimeZone
     
        在开发中,我们可以通过TimeZone对象获取关于系统默认时区及其相关的详细信息。
     
    四、Android关于日期的工具类
     
    /**
     * Copyright (C) 2011, BHJ
     * All rights reserved.
     * 
     * 文件名称:
     * 文件标识:
     * 文件摘要:
     * 
     * 当前版本:
     * 作    者:
     * 完成日期:2013-12-20
     * 
     * 取代版本:
     * 修改时间:
     * 修 改 人:
     * 修改摘要:
     */
     
    package com.bhj.timetest;
     
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.TimeZone;
     
    /**
     * 日期工具类(未特别说明的均为系统默认时区下的时间)
     * */
    public class DateUtil
    {    
        /** 1s==1000ms */
        private final static int TIME_MILLISECONDS = 1000;
        /** 时间中的分、秒最大值均为60 */
        private final static int TIME_NUMBERS = 60;
        /** 时间中的小时最大值 */
        private final static int TIME_HOURSES = 24;
        /** 格式化日期的标准字符串 */
        private final static String FORMAT = "yyyy-MM-dd HH:mm:ss";
        
        /**
         * 获取时区信息
         * */
        public static TimeZone getTimeZone()
        {
            return TimeZone.getDefault();
        }
        
        /**
         * 将日期字符串转换为Date对象
         * @param date 日期字符串,必须为"yyyy-MM-dd HH:mm:ss"
         * @return 日期字符串的Date对象表达形式
         * */
        public static Date parseDate(String date)
        {
            return parseDate(date, FORMAT);
        }
        
        /**
         * 将日期字符串转换为Date对象
         * @param date 日期字符串,必须为"yyyy-MM-dd HH:mm:ss"
         * @param format 格式化字符串
         * @return 日期字符串的Date对象表达形式
         * */
        public static Date parseDate(String date, String format)
        {
            Date dt = null;
            SimpleDateFormat dateFormat = new SimpleDateFormat(format);
            try
            {
                dt = dateFormat.parse(date);
            }
            catch(ParseException e)
            {
                e.printStackTrace();
            }
            
            return dt;
        }
        
        /**
         * 将Date对象转换为指定格式的字符串
         * @param date Date对象
         * @return Date对象的字符串表达形式"yyyy-MM-dd HH:mm:ss"
         * */
        public static String formatDate(Date date)
        {
            return formatDate(date, FORMAT);  
        }
        
        /**
         * 将Date对象转换为指定格式的字符串
         * @param date Date对象
         * @param String format 格式化字符串
         * @return Date对象的字符串表达形式
         * */
        public static String formatDate(Date date, String format)
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat(format);  
            return dateFormat.format(date);  
        }
     
        /**
         * 格式化日期
         * @param long unixTime unix时间戳
         * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
         * */
        public static String formatUnixTime(long unixTime)
        {  
            return formatUnixTime(unixTime, FORMAT);
        }
        
        /**
         * 格式化日期
         * @param long unixTime unix时间戳
         * @param String format 格式化字符串
         * @return 日期字符串
         * */
        public static String formatUnixTime(long unixTime, String format)
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat(format);  
            return dateFormat.format(unixTime);  
        }
        
        /**
         * 将GMT日期格式化为系统默认时区的日期字符串表达形式
         * @param gmtUnixTime GTM时间戳
         * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
         * */
        public static String formatGMTUnixTime(long gmtUnixTime)
        {
            return formatGMTUnixTime(gmtUnixTime, FORMAT); 
        }
        
        /**
         * 将GMT日期格式化为系统默认时区的日期字符串表达形式
         * @param gmtUnixTime GTM时间戳
         * @param format 格式化字符串
         * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
         * */
        public static String formatGMTUnixTime(long gmtUnixTime, String format)
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat(format);
            return dateFormat.format(gmtUnixTime + TimeZone.getDefault().getRawOffset()); 
        }
        
        /**
         * 获取时间戳的Date表示形式
         * @param unixTime unix时间戳
         * @return Date对象
         * */
        public static Date getDate(long unixTime)
        {  
            return new Date(unixTime);  
        }
        
        /**
         * 获取GMT时间戳的Date表示形式(转换为Date表示形式后,为系统默认时区下的时间)
         * @param gmtUnixTime GMT Unix时间戳
         * @return Date对象
         * */
        public static Date getGMTDate(long gmtUnixTime)
        {
            return new Date(gmtUnixTime + TimeZone.getDefault().getRawOffset()); 
        }
     
        /**
         * 将系统默认时区的Unix时间戳转换为GMT Unix时间戳
         * @param unixTime unix时间戳
         * @return GMT Unix时间戳
         * */
        public static long getGMTUnixTime(long unixTime)
        {
            return unixTime - TimeZone.getDefault().getRawOffset();
        }
     
        /**
         * 将GMT Unix时间戳转换为系统默认时区的Unix时间戳
         * @param gmtUnixTime GMT Unix时间戳
         * @return 系统默认时区的Unix时间戳
         * */
        public static long getCurrentTimeZoneUnixTime(long gmtUnixTime)
        {
            return gmtUnixTime + TimeZone.getDefault().getRawOffset();
        }
        
        /**
         * 获取当前时间的GMT Unix时间戳
         * @return 当前的GMT Unix时间戳
         * */
        public static long getGMTUnixTimeByCalendar()
        {
            Calendar calendar = Calendar.getInstance();
            // 获取当前时区下日期时间对应的时间戳
            long unixTime = calendar.getTimeInMillis();
            // 获取标准格林尼治时间下日期时间对应的时间戳 
            long unixTimeGMT = unixTime - TimeZone.getDefault().getRawOffset();
            return unixTimeGMT;
        }
        
        /**
         * 获取当前时间的Unix时间戳
         * @return 当前的Unix时间戳
         * */
        public static long getUnixTimeByCalendar()
        {
            Calendar calendar = Calendar.getInstance();
            // 获取当前时区下日期时间对应的时间戳
            long unixTime = calendar.getTimeInMillis();
            return unixTime;
        }
        
        /** 
         * 获取更改时区后的时间 
         * @param date 时间 
         * @param oldZone 旧时区 
         * @param newZone 新时区 
         * @return 时间
         */  
        public static Date changeTimeZone(Date date, TimeZone oldZone, TimeZone newZone) 
        {  
            Date dateTmp = null;
            if (date != null)
            {
                int timeOffset = oldZone.getRawOffset() - newZone.getRawOffset();
                dateTmp = new Date(date.getTime() - timeOffset);
            }
            return dateTmp;
        }
        
        /**
         * 将总秒数转换为时分秒表达形式
         * @param seconds 任意秒数
         * @return %s小时%s分%s秒
         */
        public static String formatTime(long seconds)
        {
            long hh = seconds / TIME_NUMBERS / TIME_NUMBERS;
            long mm = (seconds - hh * TIME_NUMBERS * TIME_NUMBERS) > 0 ? (seconds - hh * TIME_NUMBERS * TIME_NUMBERS) / TIME_NUMBERS : 0;
            long ss = seconds < TIME_NUMBERS ? seconds : seconds % TIME_NUMBERS;
            return     (hh == 0 ? "" : (hh < 10 ? "0" + hh : hh) + "小时") 
                    + (mm == 0 ? "" : (mm < 10 ? "0" + mm : mm) + "分") 
                    + (ss == 0 ? "" : (ss < 10 ? "0" + ss : ss) + "秒");
        }
        
        /**
         * 获取当前时间距离指定日期时差的大致表达形式
         * @param long date 日期
         * @return 时差的大致表达形式
         * */
        public static String getDiffTime(long date)
        {
            String strTime = "很久很久以前";
            long time = Math.abs(new Date().getTime() - date);
            // 一分钟以内
            if(time < TIME_NUMBERS * TIME_MILLISECONDS)
            {
                strTime = "刚刚";
            }
            else
            {
                int min = (int)(time / TIME_MILLISECONDS / TIME_NUMBERS);
                if(min < TIME_NUMBERS)
                {
                    if(min < 15)
                    {
                        strTime = "一刻钟前";
                    }
                    else if(min < 30)
                    {
                        strTime = "半小时前";
                    }
                    else
                    {
                        strTime = "1小时前";
                    }
                }
                else
                {
                    int hh = min / TIME_NUMBERS;
                    if(hh < TIME_HOURSES)
                    {
                        strTime = hh + "小时前";
                    }
                    else
                    {
                        int days = hh / TIME_HOURSES;
                        if(days <= 6)
                        {
                            strTime = days + "天前";
                        }
                        else
                        {
                            int weeks = days / 7;
                            if(weeks < 3)
                            {
                                strTime = weeks + "周前";    
                            }
                        }
                    }
                }
            }
            
            return strTime;
        }
    }
  • 相关阅读:
    mac c++编译出现segmentation fault :11错误
    ssh 连接缓慢解决方法
    237. Delete Node in a Linked List
    203. Remove Linked List Elements
    Inversion of Control Containers and the Dependency Injection pattern
    82. Remove Duplicates from Sorted List II
    83. Remove Duplicates from Sorted List
    SxsTrace
    使用CCleaner卸载chrome
    decimal and double ToString problem
  • 原文地址:https://www.cnblogs.com/wenfei123chai/p/4267998.html
Copyright © 2011-2022 走看看