在Android中如何获取当前时间和日期

1288

我该如何在Android应用中获取当前的时间和日期?


8
43个回答!虽然其中许多回答在撰写时是很好的,但2018年可以使用的好答案在这里 - Ole V.V.
@OleV.V. 2023年怎么样? - user16217248
2
@user16217248,我仍然推荐我之前链接的Basil Bourque的答案 - Ole V.V.
43个回答

1512

你可以使用:

import java.util.Calendar;
import java.util.Date;

Date currentTime = Calendar.getInstance().getTime();

日历中有丰富的常量,可满足您的所有需求。

请查看日历类文档


15
这非常有帮助。对于新手来说,我们需要这些小窍门...我正在使用日历获取儒略日。这比获取毫秒并计算其是否等于今天要简单得多 ;) - Bill Mote
10
这个“pull”(获取)日期和时间的来源是什么?是从安卓设备设置中获取吗? - Kyle Clegg
12
是的,它基于设备时间设置/时区。引用自文档:“Calendar的getInstance方法返回一个按照系统设置为基础的日历,并且其时间字段已经初始化为当前日期和时间”-(在类文档的第一行示例代码之上)。 - user658042
3
这只是给了我当前的秒数,介于0到60之间。在过去的几年里有什么变化吗? - adamdport
47
正如 @adamdport 所说,这并没有真正回答问题... Calendar.getInstance().getTime()Calendar.getInstance().getTimeInMillis() 都可以使用。 - akousmata
显示剩余6条评论

500
您可以使用 android.text.format.Time (但不再建议使用 - 详见下文!):
Time now = new Time();
now.setToNow();

从上面链接引用的内容:

Time类是java.util.Calendar和java.util.GregorianCalendar类的更快替代品。 Time类的实例表示一个以秒为精度的时间点。


注1:距我撰写此答案已经过去几年,而且它涉及一个旧的、特定于Android的、现在已弃用的类。Google现在“[t]这个类有很多问题,建议使用GregorianCalendar”。


注2:尽管Time类有一个toMillis(ignoreDaylightSavings)方法,但这仅是一种方便传递给期望以毫秒为单位的时间的方法。时间值只精确到一秒钟;毫秒部分始终为000。如果您在循环中执行以下操作

Time time = new Time();   time.setToNow();
Log.d("TIME TEST", Long.toString(time.toMillis(false)));
... do something that takes more than one millisecond, but less than one second ...

结果序列将重复相同的值,例如1410543204000,直到下一秒开始时,1410543205000将开始重复。


2
@InsanityOnABun和Muhammad Babar。不,不,不。文档说“精确到秒”,即使是最简单的测试(在循环中获取当前时间,使用toMillis方法并记录/打印结果),也应该告诉你,结果时间的毫秒部分为000! - ToolmakerSteve
3
如果您希望实现毫秒级的精确计时,建议使用间隔计时(interval timing)而非以时间为基准的计时(time of day)。Android文档推荐使用SystemClock.uptimeMillis()来实现间隔计时。由于大多数内置函数都使用它,因此有强烈的动力使其在所有设备上得到很好的实现。请参见SystemClock中的讨论...如果您想将其与时间相关联,在应用程序的onResume方法中,同时读取SystemClock.uptimeMillis()和Time类中的setToNow()toMillis()方法。请记住这些方法之间的区别。 - ToolmakerSteve
1
不要使用Time类(https://code.google.com/p/android/issues/detail?id=76439)。它将来会被移除,并且存在许多问题。 - Sandy Chapman
1
此类已在API级别22中被弃用,请改用GregorianCalendar。请参见此处 - Neo
实际上,在Java和后来的Android中,GregorianCalendar早已被java.time类所取代,具体而言是ZonedDateTime。对于早期的Android版本,请参阅ThreeTen-BackportThreeTenABP项目。 - Basil Bourque

447

如果您想按照指定的格式获取日期和时间,可以使用以下方法:

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
String currentDateandTime = sdf.format(new Date());

或者,

日期:

String currentDate = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(new Date());

时间:

String currentTime = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date());

10
注意,如果性能是个问题,SimpleDateFormat 可能会有问题。在我的应用中,我有一个定制的视图,其中包含约20个 HH:MM 标签,表示特定时间(长整型保存为毫秒),以及相同数量的可绘制资源。最初的测试显示,交互不如我所希望的那样流畅。当我对 onDraw() 进行分析时,发现 SimpleTimeFormatter 的调用占用了 80% 的时间。事实上,我正在阅读本页面,作为寻找更高效的格式化程序并了解日历等内容的一部分。 - William T. Mallard
@William T. Mallard:你是在onDraw()方法内创建了一个新的SimpleDateFormat实例吗? - xmen
3
可以的,但不再需要了。我没有意识到其中涉及的开销,而是认为它几乎就像一个POJO那样简单。 - William T. Mallard
38
简而言之,这行代码的作用是:将当前时间转换为格式为"年-月-日 时:分:秒"的字符串并保存在名为currentDateandTime的变量中。该代码使用了Java中的SimpleDateFormat类和Date类。 - Pratik Butani
4
你可以在中间插入sdf.setTimeZone(TimeZone.getDefault()) - Harvey
显示剩余2条评论

256

如果您更喜欢自定义格式,可以使用以下方法:

DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy, HH:mm");
String date = df.format(Calendar.getInstance().getTime());

您可以使用如下的DateFormat格式:

"yyyy.MM.dd G 'at' HH:mm:ss z" ---- 2001.07.04 AD at 12:08:56 PDT
"hh 'o''clock' a, zzzz" ----------- 12 o'clock PM, Pacific Daylight Time
"EEE, d MMM yyyy HH:mm:ss Z"------- Wed, 4 Jul 2001 12:08:56 -0700
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"------- 2001-07-04T12:08:56.235-0700
"yyMMddHHmmssZ"-------------------- 010704120856-0700
"K:mm a, z" ----------------------- 0:08 PM, PDT
"h:mm a" -------------------------- 12:08 PM
"EEE, MMM d, ''yy" ---------------- Wed, Jul 4, '01

最佳答案,带有适当的格式。干得好 - Amin Pial

129

实际上,更安全的做法是使用Time.getCurrentTimezone()设置设备上当前的时区,否则你将得到UTC时间。

Time today = new Time(Time.getCurrentTimezone());
today.setToNow();

然后,你可以获取所有你想要的日期字段,比如:

textViewDay.setText(today.monthDay + "");             // Day of the month (1-31)
textViewMonth.setText(today.month + "");              // Month (0-11)
textViewYear.setText(today.year + "");                // Year 
textViewTime.setText(today.format("%k:%M:%S"));  // Current time

请查看android.text.format.Time类以获取所有细节。

更新

正如许多人指出的那样,Google表示此类存在许多问题,不应再使用:

 

此类存在许多问题,建议改用GregorianCalendar。

 

已知问题:

 

由于历史原因,在执行时间计算时,所有算术运算都是使用32位整数进行的。这限制了可靠的时间范围从1902年到2037年。有关详细信息,请参阅Wikipedia上关于2038年问题的文章。不要依赖这种行为;它可能会在未来发生变化。对于无法存在的日期(例如由于夏令时转换而跳过的壁钟时间),调用switchTimezone(String)将导致1969年的日期(即1970年1月1日UTC之前的1秒)。大部分格式化/解析假定ASCII文本,因此不适合与非ASCII脚本一起使用。


应该从哪个包中导入时间? - ManishSB
这个类在API 22级中已被弃用。我们可以使用GregorianCalendar代替。 - Choletski

102

简而言之

Instant.now()  // Current moment in UTC.

…或者…

ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )  // In a particular time zone

详情

其他答案虽然正确,但已过时。旧的日期时间类被证明设计不佳,令人困惑和麻烦。

java.time

旧的类已被 java.time 框架取代。

这些新类受到 Joda-Time 项目的启发,由 JSR 310 定义,并由 ThreeTen-Extra 项目扩展。

请查看Oracle教程

Instant

Instant是一个时间线上的瞬间,以UTC为标准,分辨率高达纳秒级

 Instant instant = Instant.now(); // Current moment in UTC.

时区

应用一个时区(ZoneId)来获取一个ZonedDateTime。如果你省略了时区,你的JVM当前默认的时区将被隐式应用。最好明确指定所需/期望的时区。

使用格式为continent/region适当的时区名称,例如America/MontrealEurope/BrusselsAsia/Kolkata。永远不要使用3-4个字母的缩写,如ESTIST,因为它们既没有标准化,也不是唯一的。

ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Or "Asia/Kolkata", "Europe/Paris", and so on.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Table of date-time types in Java, both modern and legacy

生成字符串

您可以轻松地生成一个String作为日期时间值的文本表示。您可以选择标准格式、自定义格式或自动本地化格式。

ISO 8601

您可以调用toString方法以使用常见且明智的ISO 8601标准进行格式化的文本。

String output = instant.toString();

2016-03-23T03:09:01.613Z

请注意,对于ZonedDateTimetoString方法通过在方括号中添加时区名称来扩展ISO 8601标准。这是非常有用和重要的信息,但不是标准的。

2016-03-22T20:09:01.613-08:00[America/Los_Angeles]

自定义格式

或者使用DateTimeFormatter类指定您自己的特定格式模式。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd/MM/yyyy hh:mm a" );

指定Locale用于人类语言(英语、法语等)的翻译名称,以及定义文化规范,例如年、月和日期的顺序。请注意,Locale与时区无关。
formatter = formatter.withLocale( Locale.US ); // Or Locale.CANADA_FRENCH or such.
String output = zdt.format( formatter );

本地化

更好的做法是让java.time自动完成本地化工作。

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM );
String output = zdt.format( formatter.withLocale( Locale.US ) );  // Or Locale.CANADA_FRENCH and so on.

关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类替代了过时的旧版日期时间类,例如 java.util.Date, Calendar, 和 SimpleDateFormat

要了解更多,请参阅Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范是JSR 310Joda-Time项目现在处于维护模式,建议迁移到java.time类。

您可以直接使用与JDBC 4.2或更高版本兼容的JDBC驱动程序,无需使用字符串或java.sql.*类,即可直接将java.time对象与数据库交换。Hibernate 5和JPA 2.2支持java.time

如何获取java.time类?

Table listing which implementation of the java.time technology to use on which versions of Java and Android.


3
@giraffe.guru 请重新阅读我的回答。你错过了第三个要点。Java.time的许多功能在ThreeTen-Backport中被移植到Java 6和7,并在ThreeTenABP中进一步适用于Android。 - Basil Bourque
Instant.now()ZonedDateTime.now()需要API 26。 - Ryde
2
@Ryde 正如我对giraffe.guru所说的那样,请重新阅读我的回答。查找提到“Android”的第三个要点。 - Basil Bourque
我认为你是对的:你的新java.time版本表格比项目符号列表更直接、更易于理解。如果是我,我会稍微再复杂化一点,在ThreeTenBackport/Java 8+和ThreeTenABP/Android 26+下方加上带括号的勾选标记(或类似的东西),因为这些组合确实可以工作,只是通常没有使用它们的必要。正在开发使用ThreeTenABP并且针对Android API级别在26级以上和以下范围内的Android应用程序。在这些情况下,开发人员选择得很好。 - Ole V.V.
1
@OleV.V. 感谢您建议在图形表格中添加第二个勾选标记。我已经在后续版本的表格中使用了它。改进很大。 - Basil Bourque

85

使用以下代码获取当前日期和时间:

String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());

输出结果为:

Feb 27, 2012 5:41:23 PM

我已经获取了系统的当前日期、星期和时间,但时间没有改变。我想逐秒增加时间。我该怎么做? - Bhavesh Hirpara
3
根据安卓API,这是推荐的方法:http://developer.android.com/reference/java/text/DateFormat.html#getDateTimeInstance()。谢谢! - M Granja

65

请尝试以下方法。下面提供了获取日期和时间格式的所有格式。

    Calendar c = Calendar.getInstance();
    SimpleDateFormat dateformat = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss aa");
    String datetime = dateformat.format(c.getTime());
    System.out.println(datetime);

第一张图片

第二张图片

第三张图片


58

要获取当前时间,你可以使用Java中的标准方法System.currentTimeMillis()来获取。然后,你可以使用它来创建一个日期。

Date currentDate = new Date(System.currentTimeMillis());

正如其他人所提到的,要创建一个时间

Time currentTime = new Time();
currentTime.setToNow();

13
不需要使用 System.currentTimeMillis(),直接使用 new Date() 即可实现相同的功能。详情请见文档 - Jonik
@Jonik 在安卓中出现了 Cannot resolve constructor Date() 错误,这是因为安卓SDK使用了Java 6和7的混合版本。 - tread
@mghhgm 不是的,new Date(System.currentTimeMillis()) 是不正确的:(a)它是多余的,因为这与 new Date() 完全相同。 (b) 令人烦恼的 java.util.Date 类现在已被 java.time.Instant 取代,从 Java 8 开始。在 ThreeTen-Backport 项目中回溯到 Java 6 和 7,在早期的 Android (<26) 中则使用 ThreeTenABP - Basil Bourque

39

您可以使用以下代码:

Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strDate = sdf.format(c.getTime());

输出:

2014-11-11 00:47:55

你还可以从这里获取关于SimpleDateFormat的更多格式选项。


请注意,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat这样的老旧日期时间类现在已经成为遗留系统,被内置于Java 8及更高版本中的java.time类所取代。请参阅Oracle的教程 - Basil Bourque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接