I have date in this format for example :
12.2.2015
I have to add days to that date. For example i have to add to that date + 1000 days so the output will not be 12 . 2 . 2015 but 14 . 3 . 2018 ( it's not accurate i did not calculate it). Is there any effective algorithm for this problem or do i have to loop it and make lots of conditions about leap year etc?
So let's say you have
int year = 2015;
int month = 2;
int day = 12;
int offset = 1000;
You can utilize <ctime> functions like mktime and localtime and belief that every day has 86400 seconds to do what you need. Something like this.
#include <ctime>
struct tm orig_date;
orig_date->tm_sec = 0;
orig_date->tm_min = 0;
orig_date->tm_hour = 12; /* midday, so we make space for non-86400 errors */
orig_date->tm_mday = day;
orig_date->tm_mon = month - 1; /* uses 0-11 range */
orig_date->tm_year = year;
orig_date->tm_isdst = 0;
time_t utc = mktime(&orig_date);
utc += (offset * 86400);
struct tm *new_date;
new_date = localtime(&utc);
printf("Old date: %d. %d. %d\n", orig_date.tm_mday, orig_date.tm_mon, orig_date.tm_year);
printf("New date: %d. %d. %d\n", new_date->tm_mday, new_date->tm_mon, new_date->tm_year);
The code will produce following (which I checked to be correct):
Old date: 12. 1. 2015
New date: 8. 10. 2017
Related
I know this question has been asked a few times, and I'm asking again because I've got issues with existing solutions on SO.
My goal is to find number of days between 1900-01-01 and a given date. The date will be in the format as yyyy-mm-dd and the type is std::string.
The solution I've followed is https://stackoverflow.com/a/14219008/2633803
And below is my version:
std::string numberOfDaysSince1900v2(std::string aDate)
{
string year, month, day;
year = aDate.substr(0, 4);
month = aDate.substr(5, 2);
day = aDate.substr(8, 2);
struct std::tm a = { 0,0,0,1,1,100 }; /* Jan 1, 2000 */
struct std::tm b = { 0,0,0,std::stoi(day),std::stoi(month),std::stoi(year) - 1900 };
std::time_t x = std::mktime(&a);
std::time_t y = std::mktime(&b);
double difference;
if (x != (std::time_t)(-1) && y != (std::time_t)(-1))
{
difference = std::difftime(y, x) / (60 * 60 * 24) + 36526; //36526 is number of days between 1900-01-01 and 2000-01-01
}
return std::to_string(difference);
}
It worked fine until the given date comes to 2019-01-29 and 2019-02-01. In both cases, the output is 43494. And for the whole Feb, the output is 3 days less than expected. Then, when it comes to March 2019, the output is back to normal again.
Another case is 2019-09-03, the output is 43710, whilst the expected output is 43711.
Why would this happen to these specific dates? I ran the solution step by step and closely watched the variables in the memory but couldn't explain it.
Any suggestion is appreciated. Thanks.
The month should be represented as an integer between 0 and 11, not 1 and 12.
So
struct std::tm a = { 0,0,0,1,0,100 }; /* Jan 1, 2000 */
struct std::tm b = { 0,0,0,std::stoi(day),std::stoi(month)-1,std::stoi(year) - 1900 };
I would say there are other problems with your code. You cannot reliably initialise a tm like that (the order of fields within the struct is not guaranteed). Neither does difftime necessarily return a number of seconds (which you are assuming).
I am trying to get Week of Year. For this I am using tm * __CRTDECL localtime(const time_t * _Time) but I am not getting desired result which should be locale dependent. So I was looking for solution and some more information. I have found that there is API in JAVA Calendar.getInstance(Locale.GERMAN);.So I am just wondering whether there is such API in c/c++ as I did not find any ( not sure ). If not can anybody give me some time pointers to get Week of Year locale dependant.
The code I am using
int MyClass::getCalendarWeek(time_t time, int * p_year)
{
// Get tm structure of time parameter
tm* pCurrentTm = localtime(&time);
// determine Thursday in that week
LONG offSet = 4 - pCurrentTm->tm_wday;
if (offSet >= 4) {
offSet = -3; // Sunday
}
time += offSet * 86400L;
pCurrentTm = localtime(&time);
if (p_year) {
*p_year = pCurrentTm->tm_year + 1900;// year of current calendar week
}
return (pCurrentTm->tm_yday + 7) / 7; // current calendar week
}
Output:
11 July is in week 28 when running most locales that have monday as first day of the week, but it is week 29 for sunday as first day of week.
I am trying to write an application for an assignment and I am new to c++. A small portion of the application requires me to store a date and add an arbitrary number of days as an offset from the date. I know how I would accomplish this with Java or C# but I have been unable to find anything for c++. My professor alluded to ctime but after many searches all the examples I found had to do with the current system time. How do I create a ctime::tm struct and set it to an arbitrary date? Is it possible to add a number of days using ctime to obtain another date? For example, if I added 40 days to January 1, 2001 I would expect February 10, 2001 not January 41, 2001.
To be an example of usage
#include <stdio.h>
#include <time.h>
int main ()
{
time_t currentTime;
time(¤tTime);
struct tm * tmDate;
int day, month, year;
tmDate = localtime (¤tTime);
tmDate->tm_year = 99;
tmDate->tm_mon = 11;
tmDate->tm_mday = 10;
mktime ( tmDate );
printf("now: %d-%d-%d %d:%d:%d\n", tmDate->tm_year + 1900, tmDate->tm_mon + 1, tmDate->tm_mday, tmDate->tm_hour, tmDate->tm_min, tmDate->tm_sec);
return 0;
}
as you can see on
tmDate->tm_year = 99;
tmDate->tm_mon = 11;
tmDate->tm_mday = 10;
you can set, sub, add months, years, days .. to date.
For example simply you can add 1 month to date with
tmDate->tm_mon++;
I need to convert a given date to an int containing the number of milliseconds since Jan 1 1970. (unix epoch)
I tried the following code:
tm lDate;
lDate.tm_sec = 0;
lDate.tm_min = 0;
lDate.tm_hour = 0;
lDate.tm_mday = 1;
lDate.tm_mon = 10;
lDate.tm_year = 2010 - 1900;
time_t lTimeEpoch = mktime(&lDate);
cout << "Epoch: " << lTimeEpoch << endl;
The result is Epoch: 1288584000 which corresponds to Mon, 01 Nov 2010 04:00:00 GMT
Edit: I was expecting Oct 01 2010, apparently tm_mon is the number of months SINCE January,
so the correct line would be lDate.tm_mon = 10 -1;
As specified in the man page, tm_mon is:
The number of months since January, in the range 0 to 11.
You are likely getting confused by timezones. I think you're missing this, from the man page:
The mktime() function converts a broken-down time structure, expressed as local time...
Continuing on my attempt to create a DateTime class , I am trying to store the "epoch" time in my function:
void DateTime::processComponents(int month, int day, int year,
int hour, int minute, int second) {
struct tm time;
time.tm_hour = hour;
time.tm_min = minute;
time.tm_sec = second;
time.tm_mday = day;
time.tm_mon = month;
time.tm_year = year - 1900;
ticks_ = mktime(&time);
processTm(time);
}
void DateTime::processTm(struct tm time) {
second_ = time.tm_sec;
minute_ = time.tm_min;
hour_ = time.tm_hour;
weekday_ = time.tm_wday;
monthday_ = time.tm_mday;
yearday_ = time.tm_yday;
month_ = time.tm_mon;
year_ = time.tm_year + 1900;
}
For an arbitrary date, processComponents(5,5,1990,1,23,45) (June 6, 1990 1:23:45 am), it sets all values correctly and as expected.
However, upon further testing, I find that for processComponents(0,0,1970,0,0,0) (January 1, 1970, 12:00:00 am), mktime(&time) causes time to be screwed up:
time.tm_mon = 11;
time.tm_mday = 30;
time.tm_year = 69;
time.tm_hour = 23;
time.tm_min = 0;
time.tm_sec = 0;
time.tm_isdst = 0;
time.tm_gmtoff = -18000;
time.tm_zone = "EST";
time.tm_wday = 2;
time.tm_yday = 363;
Translating to a date of December 31, 1969 11:00:00 pm.
I can verify that mktime() is responsible, because by commenting out that line, it reports the date and time correctly as January 1, 1970 12:00:00 am.
Why is mktime() only messing up the epoch? And how should I fix / workaround this?
Thanks!
You're passing 0 as the day parameter and putting that into time.tm_mday. That component (and only that component) of struct tm is 1-based, not 0-based.
Don't ask me why.
To specify 01 Jan 1970, 12:00:00am you'd want to call it like so:
processComponents(0,1,1970,0,0,0);
And as sdtom mentioned, you'll want to make sure that tm_isdst is set appropriately - 0 for not in effect, positive for in effect, and negative for you don't know (in which case mktime() should try to guess).
Just to let you know, when I pass the date you have (0 Jan 1970, 00:00:00) to mktime() in MSVC 9 it returns an error (the passed in struct tm is untouched and the returned time_t value is -1).
Since it is off by one hour I would expect daylight savings time. Is the value of time.tm_isdst getting set somewhere? If you aren't setting it, it could be randomly getting set to 1 or 0 which would affect your results.
Passing all zeros to mktime() is interpreted as "Sun Jan 0 00:00:00 1900". Based on this, there needs to be some adjustments...
// the input is local time
// the output is seconds since the epoch
// The epoch is Jan 1, 1970 # 0:00 GMT
time_t mktime_wrapper( int month, int day, int year,
int hour=0, int min=0, int sec=0, bool isDST=-1
)
{
tm t;
t.tm_sec=sec, t.tm_min=min, t.tm_hour=hour, t.tm_isdst=isDST;
t.tm_mday=day, t.tm_mon=month-1, t.tm_year=year-1900;
return mktime( &t );
}