How can I reset a value the same day every year



  • Hi,

    How can I reset a value the same day every year? In other words I need to reset a value based on an anniversary date.

    I currently have the following code which properly resets the values, the problem with this code is that its assuming that the application will be opened on the anniversary day otherwise this will do nothing. I also tried checking if month and day are greater than current month and day but I cannot figure the correct logic.

    @void MainWindow::resetInformation()
    {
    int currentMonth = calendarWidget->selectedDate().month();
    int currentDay = calendarWidget->selectedDate().day();

    QDate anniversaryQDate = QDate::fromString(ui->label_ShowAnniversaryDate->text(), "MM/dd/yyyy");
    
     // saved in a file
    int anniversaryMonth = anniversaryQDate.month();
    int anniversaryDay = anniversaryQDate.day();
    
    if(currentMonth == anniversaryMonth)
    {
        if(currentDay == anniversaryDay)
        {
            qDebug()<< "Reset Values";
        }
    }
    

    }@

    Any idea what would be the proper logic to do this?

    FYI,
    I recently looked into the tiemspan class created by Andre and ZapB but I couldn't make it work with Qt5.

    Thanks

    EDIT: Added code, forgot to post it



  • you should save the last time that it's been executed to make sure the event doesn't get fired multiple times. Then allow some wiggle room (time) after the anniversary date, say 1 week.



  • Thank you for your reply.

    Sorry but I'm not sure on how to do what you have suggested.



  • I would do it like this:

    1. Fix whatever date you want, save it as a QDateTime "target" (in Code, in a file - however you like; but it has to be saved)
      Use e.g. QDateTime::setDate() and QDateTime::setTime.

    2. Whenever the program is launched, create another QDateTime via QDateTime::currentDateTime(), "current".

    3. Check if target.toMSecsSinceEpoch() - current.toMSecsSinceEpoch() is smaller than zero.
      If so, the resetting of your value is overdue - go ahead and reset it.
      If not, start a QTimer:
      @QTimer t();
      t.setSingleShot(true);//only needs to fire once
      t.setInterval(target.toMSecsSinceEpoch() - current.toMSecsSinceEpoch());//all objects use milliseconds
      t.setTimerType(Qt::CoarseTimer);//may be worth considering for your case
      connect(&t, SIGNAL(timeout()), objectYouNeedToInform, SLOT(someSlot()));
      t.start();@

    While the program is running you now have the ability to "notice" when the specified date and time approach, and react accordingly. If the program is only launched infrequently, it will check how much time is left and assume that it will be running until that point - to finally do what you wish it to. Or, if the specified time has already passed, it will just make up leeway and reset your value immediately.



  • Thanks a lot for your help "thEClaw"

    I think I'm close to accomplish what I want using the method you suggested, the only problem I'm having is that it keeps resetting the value once the date has passed.

    Here is my code:
    @//constructor
    checkIfItsTimeToReset();@

    @void MainWindow::resetValues()
    {
    qDebug()<< "All values have been reset";
    }
    @

    @void MainWindow::checkIfItsTimeToReset()
    {
    QDateTime currentDateTime = QDateTime::currentDateTime();
    QDateTime anniversaryDateTime = QDateTime::fromString(QString (ui->label_ShowAnniversaryDate->text()), "MM/dd/yyyy");// string saved in external file

    if((anniversaryDateTime.toMSecsSinceEpoch() - currentDateTime.toMSecsSinceEpoch()) < 0)
    {
           resetValues();
           qDebug()<< "Value is less than 0";
    }
    else
    {
         qDebug()<< "Timer has been started";
        QTimer *dateTimer = new QTimer();
        dateTimer->setSingleShot(true);//only needs to fire once
        dateTimer->setInterval(anniversaryDateTime.toMSecsSinceEpoch() - currentDateTime.toMSecsSinceEpoch());//all objects use milliseconds
        dateTimer->setTimerType(Qt::CoarseTimer);//may be worth considering for your case
    
        connect(dateTimer, SIGNAL(timeout()), this, SLOT(resetValues()));
        dateTimer->start();
    }
    

    }@

    Any idea what am I doing wrong?



  • Once the resetting has been triggered, you could replace the anniversaryDateTime by a new one (one year in the future), maybe within resetValues(). That's why you should save it.

    If that's a bad solution for you, I don't immediately have a nice idea. You could force the anniversaryDateTime to update itself, or maybe use the "%" operator at some point
    @anniversaryDateTime.toMSecsSinceEpoch() % (365864001000)//msecs in a year@

    I hope that's somewhat helpful.



  • bq. Once the resetting has been triggered, you could replace the anniversaryDateTime by a new one (one year in the future), maybe within resetValues(). That’s why you should save it.

    I don't think this would work since the anniversary date is fixed, its something the user enters when the program is first installed, and then get saved.

    Thanks a lot for your help, your suggestion definitely gave me more ideas its just a matter of thinking a little bit more.

    Thanks



  • How about this:
    @anniversaryDateTime = anniversaryDateTime.addYears(1);//overwrite your save with this@

    Of course the date can be fixed, but it won't occur again until another year has passed.



  • Hmm, these functions (addYears, addDays and addMonths) are going to be very useful, I just need to think about the best way.

    bq. Of course the date can be fixed, but it won’t occur again until another year has passed.

    I'm still a little confused on how to do it since the anniversary date entered by the user could be from years ago (10, 20... years) and I don't know how or when to overwrite it.

    Thanks a lot for opening more possibilities/ideas, that really helps. I didn't know how tricky it was to work with dates. Learning new things its awesome.

    Thanks



  • So you want to have a fixed anniversary! Why not save two values then? The original input, and the next date where a reset has to occur.

    @QDateTime anniversaryDateTime;
    QDateTime nextAnniversary;@

    Use the latter one to calculate things, to add a year when necessary, and the first one to always remember the original anniversary.



  • That is exactly what I was going to do, basically a number composed of the day and month from the original anniversaryDate and the year from currentDate. Still, I haven't figure out what I think is the hardest part, which is to reset after the anniversary date has been passed and prevent it from continuing retting every time the program is opened. I will post the code once I figure the whole thing out.

    Possible steps:
    1- Get anniversary date from user and save it
    2- Create secondAnniversaryDate based on what the user entered (day and month) and what the current date is (year).
    3- Create a new resetDate = (secondAnniversaryDate + years(1)) basically adding one year to secondAnniversaryDate
    4- Rest value after a year
    5 -Still pending - Reset value if anniversary has passed when program is open.

    Thanks a lot for your time



  • @QDateTime anniversay;//entered by user; step 1
    QDateTime theBigDay(anniversary);//just a copy
    while(theBigDay < QDateTime::currentDateTime())
    {
    theBigDay = theBigDay.addYears(1);
    }
    //now theBigDay holds the next anniversary date; step 2
    @

    And:
    @void MainWindow::resetValues()
    {
    theBigDay = theBigDay.addYears(1);//prepare for the next anniversary; step 3
    t.setInterval(theBigDay.toMSecsSinceEpoch() - current.toMSecsSinceEpoch());//step 5
    t.start();//t was your trusty QTimer

    qDebug()<< "All values have been reset";//*step 4*
    

    }@

    I won't spoil you any more fun. I hope this helps and leaves some room for you to fiddle around. :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.