I am wanting to get yesterday's date into a char in the format: YYYYMMDD (with no slashes dots etc.).
I am using this code to get toda开发者_Go百科y's date:
time_t now;
struct tm *ts;
char yearchar[80];
now = time(NULL);
ts = localtime(&now);
strftime(yearchar, sizeof(yearchar), "%Y%m%d", ts);
How would I adapt this code so that it is generating yesterday's date instead of today's?
Many Thanks.
The mktime()
function will normalise the struct tm
that you pass it (ie. it will convert out-of-range dates like 2020/2/0 into the in-range equivalent 2020/1/31) - so all you need to do is this:
time_t now;
struct tm *ts;
char yearchar[80];
now = time(NULL);
ts = localtime(&now);
ts->tm_mday--;
mktime(ts); /* Normalise ts */
strftime(yearchar, sizeof(yearchar), "%Y%m%d", ts);
how about adding
now = now - (60 * 60 * 24)
Might fail in some VERY rare corner cases (e.g. during leapseconds) but should do what you want 99.999999% of the time.
Simply subtracting one day's worth of seconds from time(NULL);
should do. Change this line:
now = time(NULL);
to this:
now = time(NULL) - (24 * 60 * 60);
Please try this code
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
int main(void)
{
char yestDt[9];
time_t now = time(NULL);
now = now - (24*60*60);
struct tm *t = localtime(&now);
sprintf(yestDt,"%04d%02d%02d", t->tm_year+1900, t->tm_mday,t->tm_mon+1);
printf("Target String: \"%s\"", yestDt);
return 0;
}
You're pretty close on. First of all, Tyler's solution will almost work -- you need to use (24*60*60*1000)
since time(3) returns milliseconds. But have a look at that struct tm
. It has fields for all the components of a date.
Update: Damn, my mistake -- time(3) does return seconds. I was thinking of another call. But have a look at the contents of struct tm
anyway.
You can manipulate the contents of the ts
struct before passing it to strftime
. The day of the month is contained in the tm_mday
member. Basic procedure:
/**
* If today is the 1st, subtract 1 from the month
* and set the day to the last day of the previous month
*/
if (ts->tm_mday == 1)
{
/**
* If today is Jan 1st, subtract 1 from the year and set
* the month to Dec.
*/
if (ts->tm_mon == 0)
{
ts->tm_year--;
ts->tm_mon = 11;
}
else
{
ts->tm_mon--;
}
/**
* Figure out the last day of the previous month.
*/
if (ts->tm_mon == 1)
{
/**
* If the previous month is Feb, then we need to check
* for leap year.
*/
if (ts->tm_year % 4 == 0 && ts->tm_year % 400 == 0)
ts->tm_mday = 29;
else
ts->tm_mday = 28;
}
else
{
/**
* It's either the 30th or the 31st
*/
switch(ts->tm_mon)
{
case 0: case 2: case 4: case 6: case 7: case 9: case 11:
ts->tm_mday = 31;
break;
default:
ts->tm_mday = 30;
}
}
}
else
{
ts->tm_mday--;
}
Edit: Yes, days of the month are numbered from 1 whereas everything else (seconds, minutes, hours, weekdays, and days of the year) are numbered from 0.
time_t now;
int day;
struct tm *ts;
char yearchar[80];
now = time(NULL);
ts = localtime(&now);
day = ts->tm_mday;
now = now + 10 - 24 * 60 * 60;
ts = localtime(&now);
if (day == ts->tm_mday)
{
now = now - 24 * 60 * 60;
ts = localtime(&now);
}
strftime(yearchar, sizeof(yearchar), "%Y%m%d", ts);
Will work with leap seconds too.
精彩评论