Android如何获取甚至负时区的UTC时区偏移

huangapple go评论83阅读模式
英文:

Android how to get UTC Timezone offset even of negative timezone

问题

我正试图将UTC偏移发送到我的服务器因此我正在使用以下代码将设备时区转换为UTC偏移

    
        TimeZone tz = TimeZone.getDefault();

        Calendar cal = GregorianCalendar.getInstance(tz);

        int offsetInMillis = tz.getOffset(cal.getTimeInMillis());

        String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));


        Log.d("UTC_Offset", offset);


现在我知道因为我使用了Math.abs它不会给我负值但我真的不知道如何获取那些处于负值的时区如GMT-07:00的Tijuana的偏移量


**注意**我对UTC中的偏移可能有误解但这个解决方案是我在Stack Overflow上找到的如果有任何解决方案或者如果我在想法上有误也请告诉我UTC是否可能为负值
英文:

Hi I am trying to send the UTC offset towards my server. So I am converting the device time zone into utc offset using following code

    TimeZone tz = TimeZone.getDefault();

    Calendar cal = GregorianCalendar.getInstance(tz);

    int offsetInMillis = tz.getOffset(cal.getTimeInMillis());

    String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));


    Log.d("UTC_Offset",offset);

Now i know as I am using the Math.abs it is not giving me the minus values but I am really dumb to know that how could I get the offset of those timezone who are in negative such as Tijuana which is GMT-07:00

Note: I may be wrong about the offset thing in UTC but this solution I found on SO. Please let me know if there is any solution or also correct me if I am wrong in idea and its that UTC could not be in negative

答案1

得分: 2

ZoneId.of("America/Tijuana").getRules().getOffset(Instant.now()).getTotalSeconds()
-25200

org.threeten.bp.ZoneId
.systemDefault()
.getRules()
.getOffset(
    Instant.now()
)
.toString()

ZoneId z = ZoneId.systemDefault();
ZoneRules rules = z.getRules();
ZoneOffset offset = rules.getOffset(Instant.now());

String output = offset.toString();

-07:00

ZoneId z = ZoneId.of("America/Tijuana");
ZoneRules rules = z.getRules();
ZoneOffset offset = rules.getOffset(Instant.now());
String output = offset.toString();

System.out.println(output);
-07:00

java.time

The modern approach uses the modern java.time classes. You are using terrible date-time classes that were years ago supplanted by java.time.

Get the [offset-from-UTC][2] of the computer’s [current default][3] [time zone][4].

ZoneId z = ZoneId.systemDefault();
ZoneRules rules = z.getRules();
ZoneOffset offset = rules.getOffset(Instant.now());

Notice that we passed a moment, represented as Instant object (a moment as seen in UTC). Politicians frequently change the offset used by the zone(s) of their jurisdiction. So the offset of your zone is likely to change over time. So you must specify a moment to ask for the offset that was in effect at that point in time.

Generate text representing that offset, using standard [ISO 8601][5] format.

String output = offset.toString();

-07:00

When receiving such text, you can parse as a ZoneOffset object.

ZoneOffset offset = ZoneOffset.parse("-07:00");

You asked:

that UTC could not be in negative

A negative offset means a place whose clocks run behind UTC. Generally, this means west (left) of the prime meridian, such as the Americas.

A positive offset means a place whose clocks run ahead of UTC. Generally, this means east (right) of the prime meridian, such as Europe, Africa, Asia.

Well, this is the commonly used meaning of positive & negative offsets, defined in the ISO 8601 standard. Some protocols and industries may use the opposite meaning. Always understand the intention of any data source you may be using.

how could I get the offset of those timezone who are in negative such as Tijuana which is GMT-07:00

ZoneId z = ZoneId.of("America/Tijuana");
ZoneRules rules = z.getRules();
ZoneOffset offset = rules.getOffset(Instant.now());
String output = offset.toString();

System.out.println(output);

-07:00


About java.time

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

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

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

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

Where to obtain the java.time classes?


<details>
<summary>英文:</summary>

# tl;dr

&gt; how could I get the offset of those timezone who are in negative such as Tijuana which is GMT-07:00


    ZoneId.of( &quot;America/Tijuana&quot; ).getRules().getOffset( Instant.now() ).getTotalSeconds() 

&gt;-25200

 - No need to do the math yourself. We have classes for this: [*java.time*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html).
 - For older Java before Java 8, use the [*ThreeTen-Backport*][1] library. 
  - For older Android, see the [*ThreeTenABP*](https://github.com/JakeWharton/ThreeTenABP) project. 
 - Avoid `Date`, `Calendar`, `SimpleDateFormat`, and `TimeZone` legacy classes.

Example:

    org.threeten.bp.ZoneId
    .systemDefault()
    .getRules()
    .getOffset​(
        Instant.now()
    )
    .toString()

To get total seconds of that offset, call `ZoneOffset::getTotalSeconds`.

    

# *java.time*

The modern approach uses the modern *java.time* classes. You are using terrible date-time classes that were years ago supplanted by *java.time*. 

Get the [offset-from-UTC][2] of the computer’s [current default][3] [time zone][4]. 

    ZoneId z = ZoneId.systemDefault() ;
    ZoneRules rules = z.getRules() ;
    ZoneOffset offset = rules.getOffset( Instant.now() ) ;

Notice that we passed a moment, represented as `Instant` object (a moment as seen in UTC). Politicians frequently change the offset used by the zone(s) of their jurisdiction. So the offset of your zone is likely to change over time. So you must specify a moment to ask for the offset that was in effect at that point in time.

Generate text representing that offset, using standard [ISO 8601][5] format.

    String output = offset.toString() ; 

&gt;-07:00

When receiving such text, you can parse as a `ZoneOffset` object.

    ZoneOffset offset = ZoneOffset.parse( &quot;-07:00&quot; ) ;

You asked:

&gt; that UTC could not be in negative

An negative offset means a place whose clocks run *behind* UTC. Generally, this means west (left) of the prime meridian, such as the Americas.

A positive offset means a place whose clocks run *ahead* of UTC. Generally, this means east (right) of the prime meridian, such as Europe, Africa, Asia.

Well, this is the commonly used meaning of positive &amp; negative offsets, defined in the ISO 8601 standard. Some protocols and industries may use the opposite meaning. Always understand the intention of any data source you may be using.

&gt; how could I get the offset of those timezone who are in negative such as Tijuana which is GMT-07:00


    ZoneId z = ZoneId.of( &quot;America/Tijuana&quot; ) ;
    ZoneRules rules = z.getRules() ;
    ZoneOffset offset = rules.getOffset( Instant.now() ) ;
    String output = offset.toString() ;

    System.out.println( output ) ;

See this [code run live at IdeOne.com][6].

&gt;-07:00

----------

# About *java.time*

The [*java.time*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html) framework is built into Java 8 and later. These classes supplant the troublesome old [legacy](https://en.wikipedia.org/wiki/Legacy_system) date-time classes such as [`java.util.Date`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Date.html), [`Calendar`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Calendar.html), &amp; [`SimpleDateFormat`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html).

To learn more, see the [*Oracle Tutorial*](http://docs.oracle.com/javase/tutorial/datetime/TOC.html). And search Stack Overflow for many examples and explanations. Specification is [JSR 310](https://jcp.org/en/jsr/detail?id=310).

The [*Joda-Time*](http://www.joda.org/joda-time/) project, now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), advises migration to the [java.time](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html) classes.

You may exchange *java.time* objects directly with your database. Use a [JDBC driver](https://en.wikipedia.org/wiki/JDBC_driver) compliant with [JDBC 4.2](http://openjdk.java.net/jeps/170) or later. No need for strings, no need for `java.sql.*` classes.

Where to obtain the java.time classes? 

 - [**Java SE 8**](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_8), [**Java SE 9**](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_9), [**Java SE 10**](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_10), [**Java SE 11**](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_11), and later  - Part of the standard Java API with a bundled implementation.
  - Java 9 adds some minor features and fixes.
 - [**Java SE 6**](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_6) and [**Java SE 7**](https://en.wikipedia.org/wiki/Java_version_history#Java_SE_7)
  - Most of the *java.time* functionality is back-ported to Java 6 &amp; 7 in [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/).
 - [**Android**](https://en.wikipedia.org/wiki/Android_(operating_system))
  - Later versions of Android bundle implementations of the *java.time* classes.
  - For earlier Android (&lt;26), the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project adapts [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) (mentioned above). See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706).


  [1]: https://www.threeten.org/threetenbp/
  [2]: https://en.wikipedia.org/wiki/UTC_offset
  [3]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/ZoneId.html#systemDefault()
  [4]: https://en.wikipedia.org/wiki/Time_zone
  [5]: https://en.wikipedia.org/wiki/ISO_8601
  [6]: https://ideone.com/jcnyIt

</details>



# 答案2
**得分**: 1

使用`SimpleDateFormat`来为您格式化:

```java
String offset = new SimpleDateFormat("Z").format(new Date());
offset = offset.substring(0, 3) + ":" + offset.substring(3);

&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; ↓↓↓↓↓ &nbsp; 如果以下部分令人困惑,请忽略答案的其余部分 &nbsp; ↓↓↓↓↓

&nbsp;

将其应用于Java虚拟机中的所有时区时的结果:

-12:00
-11:00
-10:00
-09:30
-09:00
-08:00
-07:00
-06:00
-05:00
-04:00
-03:00
-02:30
-02:00
-01:00
+00:00
+01:00
+02:00
+03:00
+04:00
+04:30
+05:00
+05:30
+05:45
+06:00
+06:30
+07:00
+08:00
+08:45
+09:00
+09:30
+10:00
+10:30
+11:00
+12:00
+12:45
+13:00
+14:00

用于打印上述结果的Java 8代码:

Instant now = Instant.now();
SimpleDateFormat fmt = new SimpleDateFormat("Z");
ZoneId.getAvailableZoneIds().stream()
    .map(z -> ZoneId.of(z).getRules().getOffset(now))
    .distinct()
    .sorted(Comparator.reverseOrder())
    .forEach(z -> {
        fmt.setTimeZone(TimeZone.getTimeZone(z));
        String offset = fmt.format(Date.from(now));
        offset = offset.substring(0, 3) + ":" + offset.substring(3);
        System.out.println(offset);
    });
英文:

Use SimpleDateFormat to format it for you:

String offset = new SimpleDateFormat(&quot;Z&quot;).format(new Date());
offset = offset.substring(0, 3) + &quot;:&quot; + offset.substring(3);

&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; ↓↓↓↓↓ &nbsp; IGNORE REST OF ANSWER IF IT IS CONFUSING &nbsp; ↓↓↓↓↓

&nbsp;

Results when applying to all TimeZones in the Java VM:

-12:00
-11:00
-10:00
-09:30
-09:00
-08:00
-07:00
-06:00
-05:00
-04:00
-03:00
-02:30
-02:00
-01:00
+00:00
+01:00
+02:00
+03:00
+04:00
+04:30
+05:00
+05:30
+05:45
+06:00
+06:30
+07:00
+08:00
+08:45
+09:00
+09:30
+10:00
+10:30
+11:00
+12:00
+12:45
+13:00
+14:00

Java 8 code to print the above:

Instant now = Instant.now();
SimpleDateFormat fmt = new SimpleDateFormat(&quot;Z&quot;);
ZoneId.getAvailableZoneIds().stream()
	.map(z -&gt; ZoneId.of(z).getRules().getOffset(now))
	.distinct()
	.sorted(Comparator.reverseOrder())
	.forEach(z -&gt; {
		fmt.setTimeZone(TimeZone.getTimeZone(z));
		String offset = fmt.format(Date.from(now));
		offset = offset.substring(0, 3) + &quot;:&quot; + offset.substring(3);
		System.out.println(offset);
	});

huangapple
  • 本文由 发表于 2020年4月8日 16:07:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/61096072.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定