標籤:android http os io 使用 java ar for 檔案
原文引自:http://www.2cto.com/kf/201312/266908.html
在開發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:14Date 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; }}
Android中關於日期時間與時區的使用總結