在java中获取当前时区的日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24806183/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 14:56:04  来源:igfitidea点击:

Get date in current timezone in java

javadatedatetimecalendartimezone

提问by Kiran Kulkarni

I have been searching over the net from past few hours to get the datetime in my system timezone.

过去几个小时我一直在网上搜索以获取系统时区中的日期时间。

When I use calendar.getTimezone.getDefaultName it always returns me GMT. (ideally it should return my current timezone, which is IST) I am trying to convert this string "2014-02-14T06:04:00:00", which is in GMT to my timezone datetime. It always returns me the same time in GMT.

当我使用 calendar.getTimezone.getDefaultName 时,它​​总是返回 GMT。(理想情况下它应该返回我当前的时区,即 IST)我试图将这个字符串“2014-02-14T06:04:00:00”(格林威治标准时间)转换为我的时区日期时间。它总是在格林威治标准时间的同一时间返回我。

All I see is that everyone is suggesting to use Timezone. i.e,

我所看到的是每个人都建议使用时区。IE,

dateFormatter.setTimezone("any_arbitary_timezone");

Point is my application will be used in different geographical locations. I cannot set it to a particular timezone. It should be set to the system timezone, so that it can display in whichever timezone the user is currently in

重点是我的应用程序将用于不同的地理位置。我无法将其设置为特定时区。它应该设置为系统时区,以便它可以显示用户当前所在的任何时区

采纳答案by Elliott Frisch

Here is a way to get the id of a TimeZonethat matches your local system clock's offset,

这是一种获取TimeZone与本地系统时钟偏移量相匹配的 id 的方法,

Calendar cal = Calendar.getInstance();
long milliDiff = cal.get(Calendar.ZONE_OFFSET);
// Got local offset, now loop through available timezone id(s).
String [] ids = TimeZone.getAvailableIDs();
String name = null;
for (String id : ids) {
  TimeZone tz = TimeZone.getTimeZone(id);
  if (tz.getRawOffset() == milliDiff) {
    // Found a match.
    name = id;
    break;
  }
}
System.out.println(name);

回答by BCza

I believe what you're looking for is the Jodalibrary. It has functionality better than the Calendar or Date classes as specified in the answer here.

我相信您正在寻找的是Joda库。它比此处答案中指定的 Calendar 或 Date 类具有更好的功能。

This functionshould be particularly useful.

这个功能应该特别有用。

回答by Basil Bourque

tl;dr

tl;博士

Use the modern java.timeclasses.

使用现代java.time类。

ZonedDateTime.now(           // Capture the current moment in the wall-clock time used by the people of a certain region (a time zone).
    ZoneId.systemDefault()   // Get the JVM's current default time zone. Can change at any moment during runtime. If important, confirm with the user.
)                            // Renders a `ZonedDateTime` object. To see the same moment in UTC, extract a `Instant` object by calling `ZonedDateTime::getInstant`.

You may omit the explicit call to ZoneId.systemDefault.

您可以省略对 的显式调用ZoneId.systemDefault

ZonedDateTime.now()          // Capture the current moment in the JVM's current default time zone.

Parse your string as a LocalDateTime, and adjust into desired time zone.

将您的字符串解析为LocalDateTime,并调整到所需的时区。

LocalDateTime.parse( "2014-02-14T06:04:00:00" )    // Parse a string lacking any indicator of time zone or offset-from-UTC. *Not* a specific point on the timeline.
             .atOffset( ZoneOffset.UTC )           // Apply UTC as we are certain that offset-from-UTC of zero was intended by the supplier of that input string. Returns a `OffsetDateTime` object.
             .atZoneSameInstant(                   // Adjust into another time zone. The `sameInstant` part means the same moment, different wall-clock time. 
                 ZoneId.of( "Africa/Tunis" )       // Specify the particular zone of interest to you.
             )                                     // Returns a `ZonedDateTime` object.

Avoid java.util.Date& .Calendar

避免java.util.Date&.Calendar

These legacy classes are notoriously troublesome. Sun/Oracle added the java.timepackage in Java 8 to supplant them. That package was inspired by Joda-Time.

这些遗留类是出了名的麻烦。Sun/Oracle在 Java 8 中添加了java.time包来取代它们。该软件包的灵感来自Joda-Time

Amongst the legacy classes' problems is this confusing behavior: While a java.util.Date has no time zone information, it's toStringimplementation applies the JVM's current default time zone when generating a String. So it misleads you by seeming to have a time zone when it does not.

遗留类的问题之一是这种令人困惑的行为:虽然 java.util.Date 没有时区信息,但它的toString实现在生成 String 时应用 JVM 的当前默认时区。因此,当它没有时区时,它似乎有一个时区,从而误导了您。

java.time

时间

I am trying to convert this string "2014-02-14T06:04:00:00", …

我正在尝试转换这个字符串“2014-02-14T06:04:00:00”,...

Your input string lacks any indicator of time zone or offset-from-UTC. So we parse as a LocalDateTime, which lacks any concept of zone/offset.

您的输入字符串缺少时区或UTC 偏移量的任何指示符。所以我们解析为 a LocalDateTime,它没有任何区域/偏移量的概念。

A LocalDateTimedoes notrepresent a moment, is nota point on the timeline. The word “Local” here does notmean a specific locality. It means “no specific locality at all”. Without the context of a zone/offset, it has no real meaning.

一个LocalDateTime不会表示一下,是不是在时间轴上的一个点。这里的“本地”一词并不是指特定的地方。它的意思是“根本没有特定的地方”。如果没有区域/偏移量的上下文,它就没有真正的意义。

LocalDateTime ldt = LocalDateTime.parse( "2014-02-14T06:04:00:00" ) ;

… which is in GMT …

......这是在格林威治标准时间......

You say you are certain the supplier of that input string intended UTC as the context. We can apply an offset-from-UTC of zero, or UTC itself, to get an OffsetDateTimeobject. An OffsetDateTimeisa moment, a point on the timeline. We can specify the ZoneOffsetusing the constant for UTC, ZoneOffset.UTC.

您说您确定该输入字符串的供应商将 UTC 作为上下文。我们可以应用 UTC 零偏移量或 UTC 本身来获取OffsetDateTime对象。AnOffsetDateTime一个时刻,时间轴上的一个点。我们可以ZoneOffset使用 UTC 常量来指定ZoneOffset.UTC

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

… to my timezone datetime

...到我的时区日期时间

Apparently you want to adjust that moment into another time zone, to see the wall-clock time used by the people of a particular region. We need to apply a time zone (ZoneId) to get a ZonedDateTime.

显然,您想将该时刻调整到另一个时区,以查看特定地区人民使用的挂钟时间。我们需要应用一个时区 ( ZoneId) 来获得ZonedDateTime.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;

Instead of specifying a time zone, you can ask your JVM for its current default time zone. Beware: The JVM's current default time zone can be changed at any moment by any code in any thread of any app within that JVM.

您可以向 JVM 询问其当前的默认时区,而不是指定时区。注意:JVM 的当前默认时区可以随时由该 JVM 中任何应用程序的任何线程中的任何代码更改。

ZoneId z = ZoneId.systemDefault() ;
ZonedDateTime zdt = odt.atZone( z ) ;

Point is my application will be used in different geographical locations.

重点是我的应用程序将用于不同的地理位置。

Simply specify your desired/expected time zones explicitly. This is alwaysgood practice, in my opinion. The default time zone lies outside your control as a programmer, which makes it unreliable.

只需明确指定您想要/期望的时区。在我看来,这总是很好的做法。默认时区超出了程序员的控制范围,这使得它不可靠。

Specify a proper time zone namein the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as ESTor ISTas they are nottrue time zones, not standardized, and not even unique(!).

以、、 或等格式指定正确的时区名称。永远不要使用 3-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。continent/regionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST

Another tip: Work, think, store, and exchange in UTC. Forget about your own parochial time zone, as translating back-and-forth to your home zone will drive you batty. Think of UTC as the One True Time, and other zones/offsets are but mere variations.

另一个提示:在 UTC 中工作、思考、存储和交流。忘记你自己的狭隘时区,因为来回转换到你的家乡时区会让你发疯。将 UTC 视为One True Time,其他区域/偏移量只是变化。

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

ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdtAuckland = instant.atZone( zAuckland ) ;

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;  
ZonedDateTime zdtKolkata = instant.atZone( zKolkata ) ;

ZoneId zCasablanca = ZoneId.of( "Africa/Casablanca" ) ;  
ZonedDateTime zdtCasablanca = instant.atZone( zCasablanca ) ;

There we have four ways ( instant, zdtAuckland, zdtKolkata, zdtCasablanca) of looking at the very same simultaneous moment, the same point on the timeline.

我们有四种方式 ( instant, zdtAuckland, zdtKolkata, zdtCasablanca) 来查看同一时刻,时间线上的同一点。

instant.toString(): 2018-05-08T20:55:14.761721Z

zdtAuckland.toString(): 2018-05-09T08:55:14.761721+12:00[Pacific/Auckland]

zdtKolkata.toString(): 2018-05-09T02:25:14.761721+05:30[Asia/Kolkata]

zdtCasablanca.toString(): 2018-05-08T21:55:14.761721+01:00[Africa/Casablanca]

Instant.toString(): 2018-05-08T20:55:14.761721Z

zdtAuckland.toString(): 2018-05-09T08:55:14.761721+12:00[太平洋/奥克兰]

zdtKolkata.toString(): 2018-05-09T02:25:14.761721+05:30[亚洲/加尔各答]

zdtCasablanca.toString(): 2018-05-08T21:55:14.761721+01:00[非洲/卡萨布兰卡]

Zone vs Offset

区域与偏移

An offset-from-UTC is simply a number of hours, minutes, and seconds. Nothing more, nothing less. Any number of time zones may share a particular offset at a particular moment.

UTC 偏移量只是小时、分钟和秒的数量。不多也不少。任何数量的时区都可以在特定时刻共享特定偏移量。

A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. For example, Daylight Saving Time (DST) is a practice where the people of a region (inexplicably) decide to change their offset twice a year.

时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史。例如,夏令时 (DST) 是一个地区的人们(莫名其妙地)决定每年更改两次偏移量的做法。

So a time zone is always preferable to a mere offset. Having a zone allows us to add or subtract time in a meaningful way, to account for changes in offset in that region's history.

所以时区总是比单纯的偏移更可取。拥有一个区域允许我们以有意义的方式增加或减少时间,以解释该地区历史中偏移量的变化。



About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多



Joda-Time

乔达时间

UPDATE: The Joda-Time project is now in maintenance mode. The team advises migration to the java.time classes. Skip to java.time section below in this Answer.

更新:Joda-Time 项目现在处于维护模式。该团队建议迁移到 java.time 类。跳到本答案下面的 java.time 部分。

The Joda-Time package has good clear support for time zones. Unlike java.util.Date, a Joda-Time DateTime does know its own assigned time zone. If you fail to specify a time zone, the JVM's current default time zone is implicitly assigned.

Joda-Time 包对时区有很好的明确支持。与 java.util.Date 不同,Joda-Time DateTime 确实知道自己分配的时区。如果未指定时区,则隐式分配 JVM 的当前默认时区。

DateTime dateTime = DateTime.now(); // Applies JVM's default time zone implicitly.

I recommend against relying on the default time zone implicitly. Doing so leads to confusion and errors when doing date-time work.

我建议不要隐式依赖默认时区。在进行日期时间工作时,这样做会导致混乱和错误。

DateTime dateTime = DateTime.now( DateTimeZone.getDefault() ); // Explicitly using default time zone.

If needed you may assign a time zone.

如果需要,您可以指定时区。

DateTime dateTimeKolkata = DateTime.now( DateTimeZone.forID( "Asia/Kolkata" ) ); // Specify a time zone.

For server-side work, best practice is to do business logic and database storage in UTC.

对于服务器端工作,最佳实践是在UTC 中进行业务逻辑和数据库存储。

DateTime dateTimeUtc = DateTime.now( DateTimeZone.UTC ); // Assign UTC (GMT) time zone.

You can convert from the assigned time zone to another, including the JVM's current default time zone.

您可以从指定的时区转换为另一个时区,包括 JVM 的当前默认时区。

DateTime dateTime = dateTimeUtc.withZone( DateTimeZone.getDefault() );

Immutable

不可变

For thread-safety, Joda-Time uses immutable objects. Instead of modifying an object, methods such as withZonecreate a new instance based on the original.

为了线程安全,Joda-Time 使用不可变对象。不是修改对象,而是withZone基于原始对象创建新实例等方法。

Parse String

解析字符串

To parse a String as a DateTime, you must note whether the String includes an offset from UTC and/or a time zone. Yours does not. So you must specify a time zone by which to interpret that String. If you do not specify, the JVM's current default time zone will be used during parsing.

要将字符串解析为 DateTime,您必须注意该字符串是否包含与 UTC 和/或时区的偏移量。你的没有。因此,您必须指定一个时区来解释该字符串。如果不指定,解析时将使用JVM当前的默认时区。

In your Question, you said the String represents a date-time in UTC(GMT).

在您的问题中,您说 String 表示UTC( GMT) 中的日期时间。

DateTime dateTimeUtc = new DateTime( "2014-02-14T06:04:00:00", DateTimeZone.UTC );

After parsing, you may assign another time zone if needed. Same moment in the time-line of the Universe, but shows a different Wall-Clock time.

解析后,您可以根据需要分配另一个时区。宇宙时间线中的同一时刻,但显示不同的挂钟时间

DateTime dateTimeDefaultZone = dateTimeUtc.withZone( DateTimeZone.getDefault() );

So notice this was a two-step process. First we parsed your String using our external knowledge of that String's intended time zone because it lacked internal representation of that time zone or offset. Secondly we adjusted the time zone to another (the JVM default zone).

所以请注意,这是一个两步过程。首先,我们使用该字符串的预期时区的外部知识来解析您的字符串,因为它缺乏该时区或偏移的内部表示。其次,我们将时区调整为另一个(JVM 默认时区)。

If your String had included an offset of +00:00or the customary Z, we could have collapsed those two steps into one.

如果您的 String 包含偏移量+00:00或惯用的Z,我们可以将这两个步骤合并为一个步骤。

DateTime dateTimeDefaultZone = new DateTime(  "2014-02-14T06:04:00:00Z", DateTimeZone.getDefault() ); // Apply time zone adjustment *after* parsing.

Note that this DateTime constructor looks like the one above but is actually quite different. This one's time zone argument is applied afterparsing, rather than duringparsing. Here the time zone argument is used to adjust the already-parsed DateTime. That Zon the end makes a world of difference.

请注意,此 DateTime 构造函数看起来与上面的类似,但实际上完全不同。这个时区参数解析之后应用,而不是解析过程中应用。这里时区参数用于调整已经解析的日期时间。这Z最终使世界变得不同。

Source of Default Time Zone

默认时区来源

The JVMinitially gets its default time zone from the host operating system. But be aware that a programmer can override this by:

JVM最初获得它的缺省时区从主机操作系统。但请注意,程序员可以通过以下方式覆盖它:

Doing this override affects all threads of all apps running in that JVM. So you should know that the JVM's default time zone is usually the same as host OS but not necessarily the same.

执行此覆盖会影响在该 JVM 中运行的所有应用程序的所有线程。所以你应该知道JVM的默认时区通常与主机操作系统相同但不一定相同。

回答by Ayaz Ahmad

      private String receivedFormat = "yyyy-MM-dd'T'HH:mm:ss", expectedFormat = "dd-MM-yyyy HH:mm:ss"; //Globall variables

        //Write these three lines in your Test Class and below 2 methods

        String dateString = "2018-08-14T07:00:00:00";
        String returnString = correctDateFormat(dateString, receivedFormat, expectedFormat);
        String result = getTimeInSelectedLocale(returnString);
    Log.i("Ayaz", "Date: " +result);



     /**
         * @param receivedDate
         * @param givenFormat
         * @param expectedFormat
         * @return returns date time in expected format
         */
        public static String correctDateFormat(String receivedDate, String givenFormat, String expectedFormat) {
            if (TextUtils.isEmpty(receivedDate)) {
                return "";
            }
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(givenFormat);
            Date newDate = null;
            try {
                newDate = simpleDateFormat.parse(receivedDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            simpleDateFormat = new SimpleDateFormat(expectedFormat);
            receivedDate = simpleDateFormat.format(newDate);
            return receivedDate;
        }



        /**
         * @param dateString
         * @return passed string date in different locale, My Db is in IST so I an converting IST in different locale
         */
        public  String getTimeInSelectedLocale(String dateString) {
            if (TextUtils.isEmpty(dateString)) {
                return dateString;
            }
            SimpleDateFormat sdf = new SimpleDateFormat(expectedFormat);
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata")); //We want Indian time to change in different locale, so this line is compulsory, you can replace with your country
            Date date1 = null;
            try {
                date1 = sdf.parse(dateString);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            //below this line -> TimeZone.getTimeZone(TimeZone.getDefault().getID(), will return current locale for example for India "Asia/Kolkata" for UAE "Asia/Dubai"
            sdf.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getID())); //This line chooses current local in which you want time
            String localDate = sdf.format(date1);
            return localDate;
        }

//I am converting the IST time "2018-08-14T07:00:00:00"  into UAE(Duabai) "14-08-2018 05:30:00" and other countries