#include <stdio.h>
#include <time.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#define TM_YEAR_SET 0x04
#define UNDEFINED -1
-static struct tm tmundef = {
+static const struct tm tmundef = {
UNDEFINED,
UNDEFINED,
UNDEFINED,
struct tm *
getdate(const char *str)
{
- static struct tm tm, *now, *result = NULL;
+ static struct tm tm;
+ struct tm *now, *result = NULL;
time_t t;
FILE *fp;
- int bufsiz, offset, len, dateset, timeset, saveerrno, wday_set;
+ int bufsiz, offset, len, dateset, timeset, saveerrno, wday_set, save_mon;
char *buf;
struct stat st;
char *file = getenv(DATEMSK);
case TM_YEAR_SET:
case TM_YEAR_SET | TM_MON_SET:
if(!(dateset & TM_MON_SET))
- tm.tm_mon = 1;
+ tm.tm_mon = 0;
tm.tm_mday = 1;
break;
tm.tm_wday = now->tm_wday;
tm.tm_gmtoff = now->tm_gmtoff; /* XXX: can't grok timezones */
tm.tm_isdst = -1;
-
+ save_mon = tm.tm_mon;
if(mktime(&tm) == (time_t)-1) {
getdate_err = INVALID_DATE;
break;
- }
- if(wday_set != UNDEFINED) {
- int delta = wday_set - tm.tm_wday;
- if(delta && (dateset & TM_MDAY_SET)) {
+ } else if ((dateset & TM_MON_SET) && (tm.tm_mon != save_mon)) { /* Did mktime fixup an overflow date? */
getdate_err = INVALID_DATE;
break;
- }
- if(delta < 0)
+ }
+ if(wday_set != UNDEFINED &&
+ (dateset != (TM_YEAR_SET | TM_MON_SET | TM_MDAY_SET))) {
+ /*
+ * We got back a week day, but not enough information to resolve it
+ * to a specific day, so we need to push forward the time to the
+ * correct wday. <rdar://problem/27439823>
+ */
+ int delta = wday_set - tm.tm_wday;
+ if(delta < 0) {
delta += 7;
+ }
tm.tm_mday += delta;
if(mktime(&tm) == (time_t)-1) {
getdate_err = INVALID_DATE;
}
}
result = &tm;
+ break;
}
} while(0);