一、概念
參考時間标準總結 IAT、UT、UTC、GMT、夏令時
1.格林尼治标準時間:Greenwich Mean Time(簡稱 GMT)
GMT 以格林尼治天文台經線為 0 度經線,将世界分為 24 個時區,向東時間快,向西時間慢。
UTC是基于标準的GMT提供的準确時間。(在計算機中 GMT 時間和 UTC 時間是一樣的)
2.夏令時與冬令時 Daylight Saving Time(簡稱 DST)
又稱“日光節約時制”和“夏令時間”,是一種為節約能源而人為規定地方時間的制度,在這一制度實行期間所采用的統一時間稱為“夏令時間”。
一般在天亮早的夏季人為将時間提前一小時,可以使人早起早睡,減少照明量,以充分利用光照資源,進而節約照明用電。各個采納夏時制的國家具體規定不同。目前全世界有近110個國家每年要實行夏令時。
自2011年3月27日開始俄羅斯永久使用夏令時,把時間撥快一小時,不再調回。
簡單來說,使用夏令時和冬令時即在夏季将時間撥快一個小時,等到冬季再将時間撥慢一個小時。
舉個例子總結一下:
假設目前 GMT 時間為 13:00,已知中原標準時間為 GMT+8(北京位于東 8 區),是以中原標準時間為 13:00 + 8 = 21:00。
但當存在夏令時時,會出現不同。比如已知莫斯科時間為 GMT+3,理論上莫斯科時間為 16:00,但是由于俄羅斯永久使用夏令時,是以實際上莫斯科時間為 17:00。
3.開發規範
在實際開發中,當時間用于顯示時,非特殊要求下一般使用系統預設的時區時間作為顯示時間。将時間做為資料存儲或傳遞給其他系統時(特别是跨平台調用),則最好使用标準的UTC/GMT時間(後面統稱GMT),除非事先約定或辨別了時間的類型。
因為使用者很有可能會有更改時區的操作出現,如果使用對應時區的時間戳,并且時間戳作為某種标記量存入了資料庫,那麼一旦時區發生改變,已存資料将會與目前時區設定産生問題;而使用标準時間戳則可以避免這一問題,因為通過程式可以很容易地将時間戳轉化為标準時間戳,并且标準時間戳是固定的,這樣就能保證即使在修改了時區的情況下,也能正确處理日期時間。
二、Calendar月曆 與 Gregorian Calendar公曆
參考Java Calendar類詳解
在曆史上有着許多種紀元的方法。它們的差異實在太大了,比如說一個人的生日是"八月八日" 那麼一種可能是陽(公)曆的八月八日,但也可以是陰(農)曆的日期。是以為了計時的統一,必需指定一個月曆的選擇。那現在最為普及和通用的月曆就是 "Gregorian Calendar"。也就是我們在講述年份時常用 "公元幾幾年"。Calendar 抽象類定義了足夠的方法,讓我們能夠表述月曆的規則。Java 本身提供了對 "Gregorian Calendar" 規則的實作。我們從 Calendar.getInstance() 中所獲得的執行個體就是一個 "GreogrianCalendar" 對象(與您通過 new GregorianCalendar() 獲得的結果一緻)。
Calendar 在 Java 中是一個抽象類(Abstract Class),GregorianCalendar 是它的一個具體實作。
我們也可以自己的 Calendar 實作類,然後将它作為 Calendar 對象傳回(面向對象的特性)。在 IBM alphaWorks 上,IBM 的開發人員實作了多種月曆。同樣在 Internet 上,也有對中國農曆的實作。本文對如何擴充 Calendar 不作讨論,大家可以通過察看上述 Calendar 的源碼來學習。
三、Date DateFormat SimpleDateFormat
java.util.Date
類 Date 表示特定的瞬間,精确到毫秒。從 JDK 1.1 開始,應該使用 Calendar 類實作日期和時間字段之間轉換,使用 DateFormat 類來格式化和分析日期字元串。Date 中的把日期解釋為年、月、日、小時、分鐘和秒值的方法已廢棄。
java.text.DateFormat(抽象類)
DateFormat 是日期/時間格式化子類的抽象類,它以與語言無關的方式格式化并分析日期或時間。日期/時間格式化子類(如 SimpleDateFormat)允許進行格式化(也就是日期 -> 文本)、分析(文本-> 日期)和标準化。将日期表示為 Date 對象,或者表示為從 GMT(格林尼治标準時間)1970 年,1 月 1 日 00:00:00 這一刻開始的毫秒數。
java.text.SimpleDateFormat(DateFormat的直接子類)
參考深入了解Java:SimpleDateFormat安全的時間格式化
SimpleDateFormat 是一個以與語言環境相關的方式來格式化和分析日期的具體類。它允許進行格式化(日期 -> 文本)、分析(文本 -> 日期)和規範化。
SimpleDateFormat 使得可以選擇任何使用者定義的日期-時間格式的模式。但是,仍然建議通過 DateFormat 中的 getTimeInstance、getDateInstance 或 getDateTimeInstance 來新的建立日期-時間格式化程式。
import java.text.SimpleDateFormat;
import java.util.Date;
public class Data {
public static void main(String[] args) {
SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd E");//可以查API,根據自己的需要顯示格式
Date date = new Date();
System.out.println("今天的日期是: "+dateFormat.format(date));
}
}
DateFormat 和SimpleDateFormat 的差別
參考日期操作類(DateFormat與SimpleDateFormat)的差別和執行個體
1.DateFormat 可以直接使用,但其本身是一個抽象類,可以根據Locate指定的區域得到對應的日期時間格式
2.SimpleDateFormat 類是DateFormat 類的子類,一般情況下來講 DateFormat 類很少會直接使用。而都使用SimpleDateFormat 類完成。
Locale
參考Locale簡介
import java.util.Locale;
public class LocaleOne {
public static void main(String[] args) {
Locale myLocale = Locale.getDefault();
System.out.println(myLocale.getCountry());//CN
System.out.println(myLocale.getLanguage());//zh
System.out.println(myLocale.getDisplayCountry());//中國
System.out.println(myLocale.getDisplayLanguage());//中文
}
}
與SimpleDateFormat一起使用:
public static final SimpleDateFormat sdfMd = new
SimpleDateFormat("M/d", Locale.getDefault());
四、在Android中需要特别注意的事項
Android中表示日期時間的類型,有Date、Calendar,他們在沒有顯示設定其時區時,取到的目前時間均為系統預設時區的時間,即使給定一個時間,同樣是按系統預設時區來換算時間,是以說他們都是與時區相關的。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);

Paste_Image.png
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());

Paste_Image.png
五、DatePickerDialog TimePickerDialog

點選按鈕

彈出選擇框

設定完成
package com.lovo;
import java.util.Calendar;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TextView;
import android.widget.TimePicker;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 獲得設定日期按鈕
Button dateBtn = (Button) findViewById(R.id.btn1);
// 獲得設定時間按鈕
Button timeBtn = (Button) findViewById(R.id.btn2);
// 為設定日期按鈕綁定監聽器
dateBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Calendar c = Calendar.getInstance();
// 直接建立一個DatePickerDialog對話框執行個體,并将它顯示出來
new DatePickerDialog(MainActivity.this,
// 綁定監聽器
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
TextView show = (TextView) findViewById(R.id.txt1);
show.setText("您選擇了:" + year + "年" + monthOfYear
+ "月" + dayOfMonth + "日");
}
}
// 設定初始日期
, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c
.get(Calendar.DAY_OF_MONTH)).show();
}
});
// 為設定時間按鈕綁定監聽器
timeBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Calendar c = Calendar.getInstance();
// 建立一個TimePickerDialog執行個體,并把它顯示出來
new TimePickerDialog(MainActivity.this,
// 綁定監聽器
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view,
int hourOfDay, int minute) {
TextView show = (TextView) findViewById(R.id.txt2);
show.setText("您選擇了:" + hourOfDay + "時" + minute
+ "分");
}
}
// 設定初始時間
, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE),
// true表示采用24小時制
true).show();
}
});
}
}
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="設定日期" />
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="設定時間" />
android:id="@+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />