4

I want my application to detect when it is a new day upon startup. If it is a new day I want it to start a new activity and repeat the cycle. for the Next Day.

I start with a calendar instance getting the day of year.

Calendar c = Calendar.getInstance();
        int thisDay = c.get(Calendar.DAY_OF_YEAR);
        long todayMillis = c.getTimeInMillis();

I then store it in a shared preferences and get another date

SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        long last = prefs.getLong("date", System.currentTimeMillis());
        c.setTimeInMillis(last);
        int lastDay = c.get(Calendar.DAY_OF_YEAR);

I am having trouble running creating the check and looping it everyday.

if (lastDay != thisDay) {
        scheduleAlarm();
        SharedPreferences.Editor edit = prefs.edit();
        edit.putLong("date", todayMillis);
        edit.commit();

}

My solution is below.

Calendar c = Calendar.getInstance();
        int thisDay = c.get(Calendar.DAY_OF_YEAR);
        long todayMillis = c.getTimeInMillis();

        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        long last = prefs.getLong("date", System.currentTimeMillis());

        c.setTimeInMillis(last);
        int lastDay = c.get(Calendar.DAY_OF_YEAR);
        // Toast.makeText(getApplicationContext(),
        // "lastday " + lastDay + "thisDay " + thisDay, Toast.LENGTH_LONG)
        // .show();
        if (lastDay == thisDay) {
            scheduleAlarm();
            SharedPreferences.Editor edit = prefs.edit();
            edit.putLong("date", todayMillis + 86400000);
            edit.commit();
        }
Sam
  • 7,252
  • 16
  • 46
  • 65
The Tokenizer
  • 1,564
  • 3
  • 29
  • 46
  • 1
    "=!" is not a legal operator, afaik. – Fildor Nov 17 '13 at 15:51
  • @Fildor That's just plain wrong. `!=` reads as `not equals` and is a perfectly legitimate operator (and if it wasn't, it'd be damned obvious due to the compile error). If what you're referring to is how it shouldn't be used for comparing equality of different objects, that's something else, but doesn't apply in this case as the comparison is on `int`s. – Vala Nov 17 '13 at 16:41
  • =! Turns into "equals not..." and "not equals", still valid, but not a non equality operator he's probably looking for. – Phix Nov 17 '13 at 17:24
  • @Thor84no I did not make any statement about `!=`. The OP wrote `=!` which seems to have been a typo. So nevermind. – Fildor Nov 17 '13 at 18:06
  • @Fildor My mistake then. When I read your statement I re-read the OP and it only used `!=`. I apparently forgot you'd placed it the other way around by the time I got round to posting, so I thought you were talking about something else. – Vala Nov 17 '13 at 19:22

2 Answers2

3

Adding some notes about Joda-Time to Sam's correct answer.

Joda-Time 2.3 makes this work easier.

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

// A good practice is to specify your time zone rather than rely on default.
org.joda.time.DateTimeZone californiaTimeZone = org.joda.time.DateTimeZone.forID("America/Los_Angeles");

// Store the datetime last examined.
org.joda.time.DateTime lastUsedStartOfDay = new org.joda.time.DateTime(californiaTimeZone).withTimeAtStartOfDay();

In the timer…

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

// In timer…
org.joda.time.DateTime now = new org.joda.time.DateTime(californiaTimeZone);
// Get the starting moment of today.
// Call "withTimeAtStartOfDay" rather than calculate midnight. Not all days in all time zones have a midnight.
org.joda.time.DateTime startOfToday = now.withTimeAtStartOfDay();
// Joda-Time has methods for comparing before, after, equals.
if ( startOfToday.isAfter(lastUsedStartOfDay)) {
    // New day has dawned.
    lastUsedStartOfDay = startOfToday; // Remember this new day.
    System.out.println( "New day has dawned: " + lastUsedStartOfDay );
} else {
    // Same day still.
    System.out.println( "Same day: " + lastUsedStartOfDay );
}

About Joda-Time…

    // Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
    // http://www.joda.org/joda-time/

    // Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
    // JSR 310 was inspired by Joda-Time but is not directly based on it.
    // http://jcp.org/en/jsr/detail?id=310

    // By default, Joda-Time produces strings in the standard ISO 8601 format.
    // https://en.wikipedia.org/wiki/ISO_8601

    // About Daylight Saving Time (DST): https://en.wikipedia.org/wiki/Daylight_saving_time

    // Time Zone list: http://joda-time.sourceforge.net/timezones.html

I omitted practical issues such as thread-safety.


Unsolicited tip: You might want to delay your activity (sleep your thread) until a few seconds or even minutes after the start of new day. Most operating systems do a bunch of work at the stroke of midnight such as rolling logs. So the stroke of midnight in computing becomes a witching hour. Best to let such utilities and daemons finish their chores before performing yours.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • +1 For mentioning *the* fully fledged alternative to the unholy, classic Java Date, which is luckily about to be replaced in Java 8 (JSR 310) – Sam Nov 17 '13 at 23:26
  • Sir, does the joda time works detect a new day even the application not open? – Sen Mar 20 '17 at 06:07
  • @Baras I do not understand your question. How can any code execute and do *anything* if its containing app is not open and running? The Joda-Time library is just plain Java code, no magic. If you want to capture the current moment, call `new DateTime`. Also, the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes built into Java 8 and later. – Basil Bourque Mar 20 '17 at 06:16
2
  • Use a Timer and schedule a single execution of a TimerTask with Timer.schedule(TimerTask task, Date when), to get notified at when (date of next day) during runtime.
  • Instead of rescheduling, you can also specify the period value (86400000 = daily) for repeated notification.
  • That task would compare the date with a stored value, e.g. a timestamp (System.currentTimeMillis()) persisted using SharedPreferences to find out, whether the date changed and write the current value back into the preferences.
  • Execute that task once on startup.
  • For simple comparisons of dates, use java.util.Calendar (time should be zeroed in your case): Compare date without time
Community
  • 1
  • 1
Sam
  • 7,778
  • 1
  • 23
  • 49
  • I am going to follow your steps, i just need to read up more on timers. – The Tokenizer Nov 17 '13 at 16:25
  • @The Tokenizer: Be wary when comparing the dates; see last bullet. – Sam Nov 17 '13 at 16:34
  • I posted my edits, I don't know how exactly I should be comparing dates – The Tokenizer Nov 17 '13 at 17:03
  • When you zero out the time like this http://stackoverflow.com/a/7784110/1175253 before comparison in both, the persisted and the current date, you can safely check for the difference of `86400000` in the timestamps returned by `Date.getTime()` (You can also construct a date from these timestamps). – Sam Nov 17 '13 at 17:13
  • How do you compare it with the timere data? – The Tokenizer Nov 17 '13 at 17:24
  • In `TimerTas.run()`: `Date timerDate = new Date(scheduledExecutionTime());` or just `Date timerDate = new Date(System.currentTimeMillis();`, as time gets truncated anyway. However, if scheduled correctly, you'd just need to store `date.getTime()`. – Sam Nov 17 '13 at 18:30