Android 时间 日期 相关

参考
Java日期时间使用总结
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

一、概念

参考时间标准总结 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中关于日期时间与时区的使用总结

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

参考Android中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();
            }
        });
    }
}


<?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="设置日期" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置时间" />

    <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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容