參考
Java日期時(shí)間使用總結(jié)
Java Calendar,Date,DateFormat,TimeZone,Locale(1) Calendar
Java Calendar,Date,DateFormat,TimeZone,Locale(2) 自己封裝的Calendar接口
Java Calendar,Date,DateFormat,TimeZone,Locale(3) Date
Java Calendar,Date,DateFormat,TimeZone,Locale(4) DateFormat
Java Calendar,Date,DateFormat,TimeZone,Locale(5) SimpleDateFormat
Java Calendar,Date,DateFormat,TimeZone,Locale(6) Locale
Java Calendar,Date,DateFormat,TimeZone,Locale(7) TimeZone
一骚勘、概念
參考時(shí)間標(biāo)準(zhǔn)總結(jié) IAT、UT、UTC纳击、GMT、夏令時(shí)
1.格林尼治標(biāo)準(zhǔn)時(shí)間:Greenwich Mean Time(簡(jiǎn)稱(chēng) GMT)
GMT 以格林尼治天文臺(tái)經(jīng)線(xiàn)為 0 度經(jīng)線(xiàn)乍恐,將世界分為 24 個(gè)時(shí)區(qū)评疗,向東時(shí)間快,向西時(shí)間慢茵烈。
UTC是基于標(biāo)準(zhǔn)的GMT提供的準(zhǔn)確時(shí)間百匆。(在計(jì)算機(jī)中 GMT 時(shí)間和 UTC 時(shí)間是一樣的)
2.夏令時(shí)與冬令時(shí) Daylight Saving Time(簡(jiǎn)稱(chēng) DST)
又稱(chēng)“日光節(jié)約時(shí)制”和“夏令時(shí)間”,是一種為節(jié)約能源而人為規(guī)定地方時(shí)間的制度呜投,在這一制度實(shí)行期間所采用的統(tǒng)一時(shí)間稱(chēng)為“夏令時(shí)間”加匈。
一般在天亮早的夏季人為將時(shí)間提前一小時(shí)存璃,可以使人早起早睡,減少照明量雕拼,以充分利用光照資源纵东,從而節(jié)約照明用電。各個(gè)采納夏時(shí)制的國(guó)家具體規(guī)定不同啥寇。目前全世界有近110個(gè)國(guó)家每年要實(shí)行夏令時(shí)偎球。
自2011年3月27日開(kāi)始俄羅斯永久使用夏令時(shí),把時(shí)間撥快一小時(shí)辑甜,不再調(diào)回衰絮。
簡(jiǎn)單來(lái)說(shuō),使用夏令時(shí)和冬令時(shí)即在夏季將時(shí)間撥快一個(gè)小時(shí)磷醋,等到冬季再將時(shí)間撥慢一個(gè)小時(shí)猫牡。
舉個(gè)例子總結(jié)一下:
假設(shè)當(dāng)前 GMT 時(shí)間為 13:00,已知北京時(shí)間為 GMT+8(北京位于東 8 區(qū))邓线,所以北京時(shí)間為 13:00 + 8 = 21:00淌友。
但當(dāng)存在夏令時(shí)時(shí),會(huì)出現(xiàn)不同骇陈。比如已知莫斯科時(shí)間為 GMT+3震庭,理論上莫斯科時(shí)間為 16:00,但是由于俄羅斯永久使用夏令時(shí)缩歪,所以實(shí)際上莫斯科時(shí)間為 17:00归薛。
3.開(kāi)發(fā)規(guī)范
在實(shí)際開(kāi)發(fā)中,當(dāng)時(shí)間用于顯示時(shí)匪蝙,非特殊要求下一般使用系統(tǒng)默認(rèn)的時(shí)區(qū)時(shí)間作為顯示時(shí)間主籍。將時(shí)間做為數(shù)據(jù)存儲(chǔ)或傳遞給其他系統(tǒng)時(shí)(特別是跨平臺(tái)調(diào)用),則最好使用標(biāo)準(zhǔn)的UTC/GMT時(shí)間(后面統(tǒng)稱(chēng)GMT)逛球,除非事先約定或標(biāo)識(shí)了時(shí)間的類(lèi)型千元。
因?yàn)橛脩?hù)很有可能會(huì)有更改時(shí)區(qū)的操作出現(xiàn),如果使用對(duì)應(yīng)時(shí)區(qū)的時(shí)間戳颤绕,并且時(shí)間戳作為某種標(biāo)記量存入了數(shù)據(jù)庫(kù)幸海,那么一旦時(shí)區(qū)發(fā)生改變,已存數(shù)據(jù)將會(huì)與當(dāng)前時(shí)區(qū)設(shè)置產(chǎn)生問(wèn)題奥务;而使用標(biāo)準(zhǔn)時(shí)間戳則可以避免這一問(wèn)題物独,因?yàn)橥ㄟ^(guò)程序可以很容易地將時(shí)間戳轉(zhuǎn)化為標(biāo)準(zhǔn)時(shí)間戳,并且標(biāo)準(zhǔn)時(shí)間戳是固定的氯葬,這樣就能保證即使在修改了時(shí)區(qū)的情況下挡篓,也能正確處理日期時(shí)間。
二、Calendar日歷 與 Gregorian Calendar公歷
參考Java Calendar類(lèi)詳解
在歷史上有著許多種紀(jì)元的方法官研。它們的差異實(shí)在太大了秽澳,比如說(shuō)一個(gè)人的生日是"八月八日" 那么一種可能是陽(yáng)(公)歷的八月八日,但也可以是陰(農(nóng))歷的日期戏羽。所以為了計(jì)時(shí)的統(tǒng)一担神,必需指定一個(gè)日歷的選擇。那現(xiàn)在最為普及和通用的日歷就是 "Gregorian Calendar"始花。也就是我們?cè)谥v述年份時(shí)常用 "公元幾幾年"妄讯。Calendar 抽象類(lèi)定義了足夠的方法,讓我們能夠表述日歷的規(guī)則衙荐。Java 本身提供了對(duì) "Gregorian Calendar" 規(guī)則的實(shí)現(xiàn)捞挥。我們從 Calendar.getInstance() 中所獲得的實(shí)例就是一個(gè) "GreogrianCalendar" 對(duì)象(與您通過(guò) new GregorianCalendar() 獲得的結(jié)果一致)。
Calendar 在 Java 中是一個(gè)抽象類(lèi)(Abstract Class)忧吟,GregorianCalendar 是它的一個(gè)具體實(shí)現(xiàn)。
我們也可以自己的 Calendar 實(shí)現(xiàn)類(lèi)斩披,然后將它作為 Calendar 對(duì)象返回(面向?qū)ο蟮奶匦?溜族。在 IBM alphaWorks 上,IBM 的開(kāi)發(fā)人員實(shí)現(xiàn)了多種日歷垦沉。同樣在 Internet 上煌抒,也有對(duì)中國(guó)農(nóng)歷的實(shí)現(xiàn)。本文對(duì)如何擴(kuò)展 Calendar 不作討論厕倍,大家可以通過(guò)察看上述 Calendar 的源碼來(lái)學(xué)習(xí)寡壮。
三、Date DateFormat SimpleDateFormat
java.util.Date
類(lèi) Date 表示特定的瞬間讹弯,精確到毫秒况既。從 JDK 1.1 開(kāi)始,應(yīng)該使用 Calendar 類(lèi)實(shí)現(xiàn)日期和時(shí)間字段之間轉(zhuǎn)換组民,使用 DateFormat 類(lèi)來(lái)格式化和分析日期字符串棒仍。Date 中的把日期解釋為年、月臭胜、日莫其、小時(shí)、分鐘和秒值的方法已廢棄耸三。
java.text.DateFormat(抽象類(lèi))
DateFormat 是日期/時(shí)間格式化子類(lèi)的抽象類(lèi)乱陡,它以與語(yǔ)言無(wú)關(guān)的方式格式化并分析日期或時(shí)間。日期/時(shí)間格式化子類(lèi)(如 SimpleDateFormat)允許進(jìn)行格式化(也就是日期 -> 文本)仪壮、分析(文本-> 日期)和標(biāo)準(zhǔn)化憨颠。將日期表示為 Date 對(duì)象,或者表示為從 GMT(格林尼治標(biāo)準(zhǔn)時(shí)間)1970 年睛驳,1 月 1 日 00:00:00 這一刻開(kāi)始的毫秒數(shù)烙心。
java.text.SimpleDateFormat(DateFormat的直接子類(lèi))
參考深入理解Java:SimpleDateFormat安全的時(shí)間格式化
SimpleDateFormat 是一個(gè)以與語(yǔ)言環(huán)境相關(guān)的方式來(lái)格式化和分析日期的具體類(lèi)膜廊。它允許進(jìn)行格式化(日期 -> 文本)、分析(文本 -> 日期)和規(guī)范化淫茵。
SimpleDateFormat 使得可以選擇任何用戶(hù)定義的日期-時(shí)間格式的模式爪瓜。但是,仍然建議通過(guò) DateFormat 中的 getTimeInstance匙瘪、getDateInstance 或 getDateTimeInstance 來(lái)新的創(chuàng)建日期-時(shí)間格式化程序铆铆。
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,根據(jù)自己的需要顯示格式
Date date = new Date();
System.out.println("今天的日期是: "+dateFormat.format(date));
}
}
DateFormat 和SimpleDateFormat 的區(qū)別
參考日期操作類(lèi)(DateFormat與SimpleDateFormat)的區(qū)別和實(shí)例
1.DateFormat 可以直接使用丹喻,但其本身是一個(gè)抽象類(lèi)薄货,可以根據(jù)Locate指定的區(qū)域得到對(duì)應(yīng)的日期時(shí)間格式
2.SimpleDateFormat 類(lèi)是DateFormat 類(lèi)的子類(lèi),一般情況下來(lái)講 DateFormat 類(lèi)很少會(huì)直接使用碍论。而都使用SimpleDateFormat 類(lèi)完成谅猾。
Locale
參考Locale簡(jiǎn)介
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());//中國(guó)
System.out.println(myLocale.getDisplayLanguage());//中文
}
}
與SimpleDateFormat一起使用:
public static final SimpleDateFormat sdfMd = new
SimpleDateFormat("M/d", Locale.getDefault());
四、在Android中需要特別注意的事項(xiàng)
參考Android中關(guān)于日期時(shí)間與時(shí)區(qū)的使用總結(jié)
Android中表示日期時(shí)間的類(lèi)型鳍悠,有Date税娜、Calendar,他們?cè)跊](méi)有顯示設(shè)置其時(shí)區(qū)時(shí)藏研,取到的當(dāng)前時(shí)間均為系統(tǒng)默認(rèn)時(shí)區(qū)的時(shí)間敬矩,即使給定一個(gè)時(shí)間,同樣是按系統(tǒng)默認(rèn)時(shí)區(qū)來(lái)?yè)Q算時(shí)間蠢挡,所以說(shuō)他們都是與時(shí)區(qū)相關(guān)的弧岳。SimpleDateFormat對(duì)象本身也是跟時(shí)區(qū)相關(guān)。當(dāng)使用parse將一個(gè)字符串格式的日期轉(zhuǎn)換為Date對(duì)象业踏,或者將一個(gè)Date對(duì)象轉(zhuǎn)換為字符串日期時(shí)禽炬,這個(gè)字符串日期的時(shí)區(qū)以SimpleDateFormat關(guān)聯(lián)的時(shí)區(qū)為準(zhǔn),如果通過(guò)setTimeZone修改了時(shí)區(qū)堡称,則這個(gè)字符串日期以修改后的時(shí)區(qū)為準(zhǔn)瞎抛。
// 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
{
//對(duì)于已經(jīng)設(shè)定為GMT時(shí)間標(biāo)準(zhǔn)的dateFormat來(lái)說(shuō),
//一切需要他轉(zhuǎn)換的字符串日期都是GMT標(biāo)準(zhǔn)時(shí)間却紧,
//轉(zhuǎn)換后返回的Date由于默認(rèn)遵守系統(tǒng)默認(rèn)時(shí)區(qū)桐臊,
//所以轉(zhuǎn)換給Date的日期需要+8(例如北京標(biāo)準(zhǔn)時(shí)區(qū)),
//也就是時(shí)區(qū)與標(biāo)準(zhǔn)不同導(dǎo)致的時(shí)差晓殊。
Date dateTmp = dateFormat.parse(dateStr);
System.out.println(dateTmp);
}
catch (ParseException e)
{
e.printStackTrace();
}
// Date還是按系統(tǒng)默認(rèn)時(shí)區(qū)断凶,而format格式化處來(lái)的字符串是GMT,所以要-8巫俺。
String dateStrTmp = dateFormat.format(date);
System.out.println(dateStrTmp);
Calendar在不手動(dòng)設(shè)置時(shí)區(qū)時(shí)认烁,是與系統(tǒng)默認(rèn)時(shí)區(qū)相關(guān)的。在手動(dòng)修改時(shí)區(qū)后,不能使用calendar.getTime方法來(lái)直接獲取Date日期却嗡,因?yàn)榇藭r(shí)的日期與setTime時(shí)的值相同舶沛,想要正確獲取修改時(shí)區(qū)后的時(shí)間,應(yīng)該通過(guò)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());
五如庭、DatePickerDialog TimePickerDialog
參考Android中DatePickerDialog對(duì)話(huà)框和TimePickerDialog對(duì)話(huà)框的使用
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);
// 獲得設(shè)置日期按鈕
Button dateBtn = (Button) findViewById(R.id.btn1);
// 獲得設(shè)置時(shí)間按鈕
Button timeBtn = (Button) findViewById(R.id.btn2);
// 為設(shè)置日期按鈕綁定監(jiān)聽(tīng)器
dateBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Calendar c = Calendar.getInstance();
// 直接創(chuàng)建一個(gè)DatePickerDialog對(duì)話(huà)框?qū)嵗⑺@示出來(lái)
new DatePickerDialog(MainActivity.this,
// 綁定監(jiān)聽(tīng)器
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 + "日");
}
}
// 設(shè)置初始日期
, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c
.get(Calendar.DAY_OF_MONTH)).show();
}
});
// 為設(shè)置時(shí)間按鈕綁定監(jiān)聽(tīng)器
timeBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Calendar c = Calendar.getInstance();
// 創(chuàng)建一個(gè)TimePickerDialog實(shí)例撼港,并把它顯示出來(lái)
new TimePickerDialog(MainActivity.this,
// 綁定監(jiān)聽(tīng)器
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view,
int hourOfDay, int minute) {
TextView show = (TextView) findViewById(R.id.txt2);
show.setText("您選擇了:" + hourOfDay + "時(shí)" + minute
+ "分");
}
}
// 設(shè)置初始時(shí)間
, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE),
// true表示采用24小時(shí)制
true).show();
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="設(shè)置日期" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="設(shè)置時(shí)間" />
<TextView
android:id="@+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>