C++ Getting Date Modified of Recycle Bin - c++

I have some simple code attempting to get the last modified date of the users recycle bin. This code seems to work on other files however it does not work on the recycle bin. I've done some looking into and it seems the recycle bin is a special file as in it's not a regular file. This would explain why I'm getting Unix epoch as the result. Here is my code:
struct tm* tmDateModified;
struct stat attribute;
stat("C:\\$Recycle.Bin\\Recycle Bin", &attribute);
tmDateModified = gmtime(&(attribute.st_mtime));
std::string date = asctime(tmDateModified);
String^ date2 = marshal_as<String^>(date);
MessageBox::Show(date2);
When I execute this code, the MessageBox displays Thu Jan 1 00:00:00 1970 as the result, again that's Unix epoch. I know this is possible as I've seen it done before in other applications, however, I don't have access to their source so I can't exactly figure out how they did it. If anyone knows why Unix epoch is being displayed rather than the actual date modified and how to fix it, I'll take any help.

Related

How can I convert IANA time zone name to UTC offset at present in Ubuntu C/C++

In Python or Java you can get the UTC offset (at present time) given the IANA name of the timezone ("America/Los_Angeles" for instance). See Get UTC offset from time zone name in python for example.
How can you do the same using C/C++ on Ubuntu 14.04?
EDIT: Preferably in a thread-safe way (no environment variables).
You alluded to this fact, but it's important to note that the offset between UTC and the time in a time zone is not necessarily constant. If the time zone performs daylight saving (summer) time adjustments, the offset will vary depending on the time of year.
One way to find the offset is to take the time you're interested in, hand it to the localtime() function, then look at the tm_gmtoff field. Do this with the TZ environment variable set to the zone name you're interested in. Here's an example that does so for the current time:
#include <time.h>
#include <stdio.h>
int main()
{
setenv("TZ", "America/Los_Angeles", 1);
time_t t = time(NULL);
struct tm *tmp = localtime(&t);
printf("%ld\n", tmp->tm_gmtoff);
}
At the moment this prints -25200, indicating that Los Angeles is 25200 seconds, or 420 minutes, or 7 hours west of Greenwich. But next week (actually tomorrow) the U.S goes off of DST, at which point this code will start printing -28800.
This isn't guaranteed to work, since the tm_gmtoff field is not portable. But I believe all versions of Linux will have it. (You might have to compile with -D_BSD_SOURCE or something, or refer to the field as __tm_gmtoff. But in my experience it tends to work by default, as plain tm_gmtoff.)
The other way is to go back and forth with gmtime and mktime, as described in Sam Varshavchik's answer.
Addendum: You asked about not using environment variables. There is a way, but unfortunately it's even less standard. There are BSD functions tzalloc and localtime_rz which do the job, but they do not exist on Linux. Here's how the code looks:
timezone_t tz = tzalloc("America/Los_Angeles");
if(tz == NULL) return 1;
time_t t = time(NULL);
struct tm tm, *tmp = localtime_rz(tz, &t, &tm);
printf("%ld\n", tmp->tm_gmtoff);
For me this prints -28800 (because PDT fell back to PST just a few minutes ago).
If you had it, you could also use localtime_rz along with mktime in Sam Varshavchik's answer. And of course Howard Hinnant's library is pretty obviously thread-safe, not requiring mucking with TZ at all.
EDIT (OP): The code for localtime_rz and tzalloc can be downloaded from https://www.iana.org/time-zones and works on Ubuntu 14.04.
You could use this free open source C++11/14 library to do it like this:
#include "chrono_io.h"
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
auto zt = make_zoned("America/Los_Angeles", system_clock::now());
std::cout << zt.get_info().offset << '\n';
}
This currently outputs:
-25200s
Or you could format it differently like this:
std::cout << make_time(zt.get_info().offset) << '\n';
which currently outputs:
-07:00:00
The factory function make_zoned creates a zoned_time using the IANA name "America/Los_Angeles" and the current time from std::chrono::system_clock. A zoned_time has a member getter to get the information about the timezone at that time. The information is a type called sys_info which contains all kinds of useful information, including the current UTC offset.
The UTC offset is stored as a std::chrono::seconds. The header "chrono_io.h" will format durations for streaming. Or the make_time utility can be used to format the duration into hh:mm:ss.
The program above is thread-safe. You don't have to worry about some other process changing TZ out from under you, or changing the current time zone of the computer in any other way. If you want information about the current time zone, that is available too, just use current_zone() in place of "America/Los_Angeles".
If you wanted to explore other times, that is just as easy. For example beginning at Nov/6/2016 at 2am local time:
auto zt = make_zoned("America/Los_Angeles", local_days{nov/6/2016} + 2h);
The output changes to:
-28800s
-08:00:00
More information about this library was presented at Cppcon 2016 and can be viewed here:
https://www.youtube.com/watch?v=Vwd3pduVGKY
Use gmtime(), first, to convert the current epoch time into UTC time, then use mktime() to recalculate the epoch time, then compare the result to the real epoch time.
gmtime() calculates the struct tm in UTC, while mktime() assumes that the struct tm represents the current local calendar time. So, by making this round-about calculation, you indirectly figure out the current timezone offset.
Note that mktime() can return an error if struct tm cannot be convert to epoch time, which will happen during certain transitions between standard time and alternate time. It's up to you to figure out what that means, in your case.
The recipe looks something like this:
time_t t = time(NULL);
struct tm *tmp = gmtime(&t);
time_t t2 = mktime(tmp);
int offset = t - t2;
See the documentation of these library functions for more information.
To use a specific time zone, either set the TZ environment variable, or you can try using localtime_rz as in Steve Summit's answer. As mentioned, beware that mktime can sometimes return -1 for unconvertible times.

boost day_clock::local_day() conundrum

I have this piece of code which executes on a machine in Frankfurt:
//hardcoding for simplicity but these get passed
int year = 2016;
int month = 05;
int day = 6;
boost::gregorian::date gdToday (boost::gregorian::day_clock::local_day());
LOG(DEBUG, 0) << " today=" << gdToday;
if (boost::gregorian::date(year, month, day) > gdToday)
{
// log
return;
}
In my log, I see this:
2016-05-06 02:40:40.479057 | DEBUG | today=2016-May-05
I know that the log timestamp is in UTC. I assume that day_clock::local_day() is giving me CEST time.
So 2016-05-06 02:40 UTC will be 2016-05-06 04:40.
But why is gdToday still giving me 2016-May-05?
Because of this, the if comparison is failing.
I have trying to read the boost doc but still dont have much clue. Could it be boost::gregorian::date::operator<<. I dont think using day_clock::universal_day() would be any useful either.
Any hints or ideas?
Thanks!!
Interesting. We can't see anything without knowing locales and timezones in effect of course. Your assumption doesn't cut it.
Going out on a limb, because you don't actually show how you get the local_day displayed in the log, I could theorize that you accidentally hardcoded the day into a formatter instead of using a lazy actor (all boost formatters are lazy actors that get invoked at log message formatting time).
This would mean it never progresses to the next day in the first place, unless your format is re-initialized (e.g. process restart).

Getting incorrect file modification time using stat APIs

I see a strange behavior while fetching the modification time of a file.
we have been calling _stat64 method to fetch the file modification in our project as following.
int my_win_stat( const char *path, struct _stati64 *buf)
{
if(_stati64( path, buf) == 0)
{
std::cout<<buf->st_mtime << std::endl; //I added to ensure if value is not changing elsewhere in the function.
}
...........
...........
}
When I convert the epoch time returned by st_mtime variable using epoch convertor, it shows 2:30 hrs ahead of current time set on my system.
When I call same API as following from different test project, I see the correct mtime (i.e. according to mtime of file shown by my system).
if (_stat64("D:\\engine_cost.frm", &buffer) == 0)
std::cout << buffer.st_mtime << std::endl;
Even I called GetFileTime() and converted FILETIME to epoch time with the help of this post. I get the correct time according to time set the system.
if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
{
ULARGE_INTEGER ull;
ull.LowPart = ftWrite.dwLowDateTime;
ull.HighPart = ftWrite.dwHighDateTime;
std::cout << (ull.QuadPart / 10000000ULL - 11644473600ULL);
}
What I am not able to figure out is why does the time mtime differ when called through my existing project?
What are the parameters that could affect the output of mtime ?
What else I could try to debug the problem further ?
Note
In VS2013, _stati64 is a macro which is replaced replaced by _stat64.
File system is NTFS on windows 7.
Unix time is really easy to deal with. It's the number of seconds since Jan 1, 1970 (i.e. 0 represents that specific date).
Now, what you are saying is that you are testing your time (mtime) with a 3rd party tool in your browser and expects that to give you the right answer. So... let's do a test, the following number is Sept 1, 2015 at 00:00:00 GMT.
1441065600
If you go to Epoch Converter and use that very value, does it give you the correct GMT? (if not, something is really wrong.) Then look at the local time value and see whether you get what you would expect for GMT midnight. (Note that I use GMT since Epoch Converter uses that abbreviation, but the correct abbreviation is UTC.)
It seems to me that it is very likely that your code extracts the correct time, but the epoch convertor fails on your computer for local time.
Note that you could just test in your C++ program with something like this:
std::cerr << ctime(&buf->st_mtime) << std::endl;
(just watch out as ctime() is not thread safe)
That will give you the data according to your locale on your computer at runtime.
To better control the date format, use strftime(). That function makes use of a tm structure so you have to first call gmtime or localtime.
An year later I ran into the similar problem but scenario is little different. But this time I understand why there was a +2:30Hrs of gap. I execute the C++ program through a perl script which intern sets the timezone 'GMT-3' and my machine had been in timezone 'GMT+5:30'. As a result there was a difference of '2:30Hrs'.
Why ? As Harry mentioned in this post
changing the timezone in Perl is probably causing the TZ environment variable to be set, which affects the C runtime library as per the documentation for _tzset.

how to use mktime to respect timezone

How do I create timezone aware struct tm in Linux/gcc ?
I have the following code:
struct tm date;
date.tm_year=2012-1900;
date.tm_mon=9;
date.tm_mday=30;
date.tm_hour=17;
date.tm_min=45;
date.tm_sec=0;
date.tm_zone="America/New_York";
time_t t = mktime(&date);
When I print t the value is 1349045100. So I take this uses both c++ and python to print as string, it returns me: Sun Sep 30 18:45:00 2012 which is one hour off. I want 17:45 not 18:45. The python command I am using is:
time.ctime(1349045100)
C++ I am using is:
::setenv("TZ", "America/New_York",1);
::tzset();
strftime(tm_str, len_tm_str, "%Y%m%d %H:%M:%S", ::localtime(&t));
So it seems when I construct the time it is already one hour off. How do I correct this?
You problem is almost certainly that the tm_isdst flag of your tm struct defaulted to 0 which caused it to assume no DST even in summer (which your date is). Then when you converted back to localtime it DID add the DST offset, causing the difference you note.
The simplest and often correct solution is to set the tm_isdst member to -1 to let mktime figure out if the date in question should have a DST offset applied.
Note that whether DST is in effect is orthogonal to which timezone you're using. Both need to be set in the correct way for the results to come out correctly.
Also do consider using localtime_r instead of localtime if there's any chance of your application being threaded.

Convert UTC time_t to different timezones C++ thread safe

[Updated]
I am trying to find to correct way to convert a timestamp in UTC to different timezones.
The exact problem: I have timestamps in my program and its always stored in UTC so its fine. however, i have to be able to display them (actually write them to files) in different timezones according to user preferences.
I am working on linux but I would like to write pateform-independant code.
I don't want to use boost libraries (we are already using Qt which does not provide as much functions as boost for dates).
I would like to write thread-safe code
I would like to identify the timezones like US/Eastern to simplify the configuration (it is done by users and im not very confident that they would make correct use of the abbreviations like EST, CET, CEST...).
I already looked on Internet and found some more or less working code but
most of the time it uses the TZ env variable which is said to be a not thread-safe method.
It uses abbreviations for the timezone (like EST, CET...).
Could anybody indicate me a good approach?
Here is what I have now (found on Internet some days ago and modified to used my Qt library in this example).
This code is probably not thread-safe.
NEW VERSION:
Still not thread-safe but it more or less do the job.
Probably not easily portable to window environment.
It handles the daylight change
see bellow example (daylight change in Paris happens on 25 Mars 2012 at 01H00 UTC (passing from 02H00 localtime at 03H00 localtime).
It is an example to convert Timestamp from UTC to Paris (has daylight change) & Kuala_Lumpur (does not have daylight change).
#include <QtCore/QCoreApplication>
#include <QDateTime>
#include <stdio.h>
#include <stdlib.h>
#include <QDebug>
void treatTimestamp(QString timestamp,QString format);
int main(int argc, char *argv[])
{
QString format = "MM:dd:yyyy hh:mm:ss";
treatTimestamp("03:25:2012 00:59:59",format);
qDebug()<<"---------------------";
treatTimestamp("03:25:2012 01:00:00",format);
return 0;
}
void treatTimestamp(QString timestamp_s,QString format)
{
unsetenv("TZ");
setenv("TZ", "UTC", 1);
QDateTime timestamp = QDateTime::fromString(timestamp_s, format);
qDebug()<<"CUSTOM TS UTC:"<<timestamp.toUTC().toString(format).toStdString().c_str();;
time_t tmp = timestamp.toUTC().toTime_t();
setenv("TZ", ":Asia/Kuala_Lumpur", 1);
qDebug()<<"CUSTOM TS KL:"<<QDateTime::fromTime_t(tmp).toString(format);
setenv("TZ", "Europe/Paris", 1);
qDebug()<<"CUSTOM TS Paris:"<<QDateTime::fromTime_t(tmp).toString(format);
unsetenv("TZ");
}
Output (First : one second before the timechange, Second: one second after).
CUSTOM TS LOC: 03:25:2012 01:00:00
CUSTOM TS UTC: 03:25:2012 01:00:00
CUSTOM TS KL: "03:25:2012 09:00:00"
CUSTOM TS Paris: "03:25:2012 03:00:00"
CUSTOM TS LOC: 03:25:2012 03:00:00
CUSTOM TS UTC: 03:25:2012 03:00:00
CUSTOM TS KL: "03:25:2012 11:00:00"
CUSTOM TS Paris: "03:25:2012 05:00:00"
According to this thread, using QDateTime it is possible to do dateTime.addSecs(3600*timeZoneOffset); where dateTime is QDateTime.
According to gmtime reference, there's no built-in timezone support in C library, but you can "kinda" simulate them by adding requiring offset to tm->tm_hour. Which won't adjust date correctly (unlike QDateTime method), by the way.
According to mktime reference, mktime will "normalize" datetime values, so you could add time offset to tm_hour, call mktime. However, it isn't specified HOW mktime adjusts fileds of struct tm - if you say, set tm_hour to 27, will it clamp tm_hour to 23 or will set tm_hour to 3, increasing tm_day (and possibly month/year)?
If I were you, I'd simply use QDateTime::addSecs method.
I give +1 to SigTerm as his answers have been constructive.
In the end i validate with users that one running process will only need 2 timezones : a specified one and the UTC one (mostly for logging).
So in the end I use this at the top of the program
unsetenv("TZ");
setenv("TZ", "", 1);
Then in the specific parts where i need UTC time i always call the Qt toUTC method.
It is really not satisfying but the full software is about data acquisition and the timestamp is an important part of it so i didn't want to make my own calculation in the code.
I heard that Qt5 will have an implementation of timezone manipulation similar to what exists in the boost library. Maybe ill refactor the code when it will be out,.