Android countdown based on GMT/UTC and not the use

2019-06-11 05:47发布

问题:

small problem here. I have an android countdown timer that works fine, but the issue is the countdown timer will be different between users/timezone. By this I mean, for every timezone, users of my app will see a different countdown that may end earlier or later relative to their timezone.I don't want this, I want it so all countdowns end at the same time for THIS movie release.

My code: Note: some code is omitted for brevity and please check out the comments below for some explanation of the code

        // the current date and time
        Calendar today = Calendar.getInstance();


    // release.date is in milliseconds at 12am and in GMT, example: GMT: Friday, September 29, 2017 12:00:00 AM
    long currentTimeMillis = today.getTimeInMillis();
    long expiryTime = releaseDate.date - currentTimeMillis;


    holder.mTextCountdown.setText("");
    if (holder.timer != null) {
        // Cancel if not null to stop flickering
        holder.timer.cancel();
    }
    holder.timer = new CountDownTimer(expiryTime, 500) {
        public void onTick(long millisUntilFinished) {
            long seconds = millisUntilFinished / 1000; // reminder: 1 sec = 1000 millis
            long minutes = seconds / 60;
            long hours = minutes / 60;
            long days = hours / 24;

            String dayFormat = "days";
            String hoursFormat = "hours";
            if (days == 1) {
                dayFormat = "day";
            }
            if (hours == 1) {
                hoursFormat = "hour";
            }
            String time = days + " " + dayFormat + " : " + hours % 24 + " " + hoursFormat +" : " + minutes % 60 + " : " + seconds % 60;
            holder.mTextCountdown.setText(time);
        }

        // Finished: counted down to 0
        public void onFinish() {
            holder.mTextCountdown.setText("Now out!");
        }
    }.start();

How can I count down a timer in GMT/UTC, where for every user it's sure to end at the same time?

Thank you

回答1:

I'd recommend you to do following 2 things:

  1. Store all times in UTC, and convert it to local timezone only for UI output
  2. Synchronize time (and set it) from server side. Anyway, you can't control what time is it now at client device — it can be in wrong timezone, or have time servers off by some reason, and local time can be incorrect. Just sync time on user device with server time, store the delta if any, and show countdown based on server time.


回答2:

Use modern java.time classes rather than the troublesome old Calendar/Date classes. For Android, see the last bullets below.

Say your movie releases at 5 PM in Los Angeles time on September 23rd.

LocalDate ld = LocalDate.of( 2017 , 9 , 23 ) ;
LocalTime lt = LocalTime.of( 17 , 0 ) ;

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

Convert that to UTC, a Instant object.

Instant instant = zdt.toInstant() ;  // Convert from a time zone to UTC. Same point on the timeline.

Calculate the time until then, as a Duration.

Duration d = Duration.between( Instant.now() , instant ) ;

Extract your number of milliseconds.

long millis = d.toMillis() ;

Perhaps you want to show the movie release date-time to a user in Québec.

ZonedId zUser = ZoneId.of( "America/Quebec" ) ;
ZonedDateTime zdtUser = instant.atZone( zUser ) ;  // Adjust into user’s time zone. Some point on the timeline.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String output = zdtUser.format( f ) ;

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.

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

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

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
    • See How to use ThreeTenABP….