Bruno Morales Bruno Morales - 2 months ago 13
Android Question

set date in EST - Android

The idea is to build an event (custom class Event) where the user can write the time he wants the event to be at in hours and minutes and select the date from a calendarView.
So I get the date he picked from the view and the time he wants the event to begin at and put them into the event object. Problem is that when I create it it will set the date to GMT-3 (my Default), but I want the date to be in EST. Since the app will be mainly used by people using the EST format, if I create the event it will display it wrong for them and viceversa, and if I want to set up notifications for these events they won't be correct.
Is there a way to create a date in EST?

In this way, if they create a date in EST and I read it from my phone, it will display it in my timezone won't it?

Answer

tl;dr

Capture input.

Instant instant = 
    OffsetDateTime.of( LocalDate.of( 2016 , 1 , 2 ) , 
                       LocalTime.of( 12 , 34 , 56 ) , 
                       ZoneOffset.ofHours( -3 ) 
                     )
                  .toInstant() ;

Generate output for presentation in any time zone with any Locale.

String output = 
    instant.atZone( ZoneId.of( "Pacific/Auckland" ) )
           .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
                                     .withLocale( Locale.CANADA_FRENCH ) 
                  ) ;

Use proper time zone names

Specify a proper time zone name. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

Offset versus time zone

An offset-from-UTC is a number of hours and minutes and seconds different from UTC that a particular locality of people use in setting the time on their clocks, the wall-clock time.

A time zone is an offset plus a set of rules for handling anomalies.

So GMT-3 is not your time zone, it is your offset. Your time zone might be America/Buenos_Aires, Antarctica/Rothera, or such.

Since a time zone provides more information and more features, always use a time zone in preference over a mere offset.

Tip: Always write out an offset with padding zeros and with both hour and minutes separated by colon. The other variations are permitted by the ISO 8601 standard, but are sometimes not supported in various protocols or software systems. So use -03:00 rather than -3.

Avoid legacy date-time classes

Do not use the notoriously troublesome old legacy classes bundled with the earliest versions of Java. Avoid java.util.Date, java.util.Calendar, SimpleDateFormat, and such. Now supplanted by the java.time classes.

LocalDate & LocalTime

The LocalDate and LocalTime types in java.time represent a date-only or time-of-day-only value, and without time zone. Use these to collect data from your widgets. “Local” means “un-zoned”, lacking in offset or time zone meaning.

LocalDate ld = LocalDate.of( 2016 , 1 , 2 );
LocalTime lt = LocalTime.of( 12 , 34 , 56 );

OffsetDateTime

If all we have is an offset of three hours rather than a full time zone, interpret that pair of LocalDate & LocalTime as a OffsetDateTime object with a ZoneOffset object.

ZoneOffset offset = ZoneOffset.ofHours( -3 );
OffsetDateTime odt = OffsetDateTime.of( ld , lt , offset );

ZonedDateTime

If we do have a time zone in mind, apply a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( "America/Buenos_Aires" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );

Instant

Do much of your business logic, data storage, and data exchange in UTC. Apply offset or time zone only where needed such as presentation to the user.

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.

You can extract a Instant object from the other types.

Instant instant = zdt.toInstant();

Adjust the instant into any other time zones you may desire.

ZonedDateTime zdtNewYork = instant.atZone( ZoneId.of( "America/New_York" ) );
ZonedDateTime zdtParis = instant.atZone( ZoneId.of( "Europe/Paris" ) );
ZonedDateTime zdtAuckland = instant.atZone( ZoneId.of( "Pacific/Auckland" ) );

These objects all represent the same moment, the same point on the timeline. They are different only in that we are viewing the same moment through the lens of each locality’s wall-clock time.

Strings

Keep in mind that strings are not date-time values; they are a representation in text of the date-time value.

So a date-time object can generate a String in any format you desire. You can specify a custom format. But generally best to let java.time automatically localize for you.

To localize, specify:

  • FormatStyle to determine how long or abbreviated should the string be.
  • Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.

Example:

Locale l = Locale.CANADA_FRENCH ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );

Note that Locale is orthogonal to time zone, completely unrelated. You can have a French presentation of an Pacific/Auckland zoned value, or a Hindu presentation of a Europe/Copenhagen zoned value.

About java.time

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

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

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

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

The ThreeTen-Extra project 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.

Comments