Search code examples
javaandroidtimezonedst

How to detect Daylight Saving Time transition in android


I have an android app that has a service witch fires an alert based on some time calculation.

The problem is when the timezone changes (i.e.: For a user who's located France and goes from UTC+1 to UTC+2). The application is not notified about this change and so, it fires the alert with a delay.

I have already checked android TimeZone API and know that there are some methods which can help, like:

IS IT POSSIBLE to know when the change will happen, in order to consider it in my calculation algorithm?

BTW: I already checked a lot of blogs and Q/A from Stackoverflow but don't help :(

EDIT (manifest file and receiver class):

Here is my manifest:

<receiver android:name=".receiver.NotificationReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.TIMEZONE_CHANGED" />
    </intent-filter>
</receiver>

Receiver class:

public class NotificationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        WakeLock.acquire(context);
        Intent service = new Intent(context, NotificationService.class);
        service.putExtras(intent);
        context.startService(service);

        // Timezone or time change
        if (intent.getAction() != null
            && (intent.getAction().equals(Intent.ACTION_TIME_CHANGED)
                || intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)))
        {
            Intent i = new Intent(context, DialogPopUpTimeChange.class);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        }
    }
}

Solution

  • Well, here is how I resolved this issue:

    1- I kept the Android Manifest as it is (see the question)

    2- Then i changed the receiver a bit:

    public class NotificationReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            WakeLock.acquire(context);
            // Timezone or time change
            if (intent.getAction() != null
                && (intent.getAction().equals(Intent.ACTION_TIME_CHANGED)
                || intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)))
            {
                calculateTimeZone(context);
            }
        }
    }
    

    3- Here is the method that calculates the new timezone and the use of DST:

    public void calculateTimeZone(Context context) {
        float ONE_HOUR_MILLIS = 60 * 60 * 1000;
    
        // Current timezone and date
        TimeZone timeZone = TimeZone.getDefault();
        Date nowDate = new Date();
        float offsetFromUtc = timeZone.getOffset(nowDate.getTime()) / ONE_HOUR_MILLIS;
    
        // Daylight Saving time
        if (timeZone.useDaylightTime()) {
            // DST is used
            // I'm saving this is preferences for later use
    
            // save the offset value to use it later
            float dstOffset = timeZone.getDSTSavings() / ONE_HOUR_MILLIS;
            // DstOffsetValue = dstOffset
            // I'm saving this is preferences for later use
    
            // save that now we are in DST mode
            if (timeZone.inDaylightTime(nowDate)) {
                // Now you are in use of DST mode
                // I'm saving this is preferences for later use
            } else {
                // DST mode is not used for this timezone
                // I'm saving this is preferences for later use
            }
        }
    }
    

    That's it. So, the solution was to combine all the ApIs (listed in the question) together.

    I hope that this solution will help other. If you have any question just post it in comment