-1

I tried to get the date of first Sunday in this year

int getFristSunday () {
    time_t rawtime;
    struct tm * timeinfo;
    time( &rawtime );
    timeinfo = localtime( &rawtime );
    timeinfo->tm_mon = 0;
    timeinfo->tm_wday = 0;
    mktime( timeinfo );
    return timeinfo->tm_yday ;
}

but I get the first Thursday

Result

  • Start with Jan-1, and iterate until you get to Sunday. It never takes more than six iterations. – Sergey Kalinichenko Feb 07 '16 at 11:20
  • @dasblinkenlight as `mktime()` works in locale time, setting to Jan 1 may be insufficient as `mktime()` may render that that to Jan 2 due to a difference between DST setting of now and Jan 1 and "now" being near midnight. Depending on how iterations are done, may result in an answer of Jan 8. Need to insure DST correct does not change the date. – chux - Reinstate Monica Feb 08 '16 at 23:47

3 Answers3

1

From this mktime reference:

time->tm_wday and time->tm_yday are ignored.

You have to set timeinfo->tm_mday to 1 and then check what day it is after calling mktime, and count forward from there.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Using this free, open-source, header-only C++11/14 library:

#include "date.h"
#include <iostream>

int
main()
{
    using namespace date;
    std::cout << year_month_day{sun[1]/jan/2016} << '\n';
}

which outputs:

2016-01-03

There are year(), month() and day() accessors for the year_month_day object. And the algorithms are highly optimized (containing no iterative loops).

If you would prefer to write your own date computations, here are the public domain calendrical algorithms used in the aforementioned date library. The link goes straight to the section describing how to find the Nth day of the week of the month/year combination.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
0

Before calling mktime() all fields, except tm_yday and tm_wday need to be set. Obviously we need to set tm_mon and tm_mday for Jan 1.

Important to set the tm_hour to midday (12) and/or tm_isdst to -1 to insure the recalculated time is not impacted by daylight saving time. Consider what would happen if the current time was near midnight and the DST setting for now was different than Jan 1. The re-calculation could push time out of Jan 1 to Jan 2 or Dec 31.

int getFirstSunday(void) {
  time_t rawtime;
  struct tm * timeinfo;
  time(&rawtime);
  timeinfo = localtime(&rawtime);

  timeinfo->tm_mon = 0;     // set to January which is 0 "Months since January"
  timeinfo->tm_mday = 1;    // Set to the 1st of the month

  timeinfo->tm_hour = 12;  // Set to avoid getting the wrong DST setting for Jan 1.
  timeinfo->tm_isdst = -1; // Set to avoid getting the wrong DST setting for Jan 1.

  if (mktime(timeinfo) == -1) return -1;
  int DaysSinceSundayForJan1 = timeinfo->tm_wday;  // days since Sunday — [0, 6]
  int DaysAfterJan1toNextSunday = 7 - DaysSinceSundayForJan1;
  int DaysAfterJan1toFirstSunday = DaysAfterJan1toNextSunday%7;
  // Convert to "day of the month"
  return DaysAfterJan1toFirstSunday + 1;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256