FILETIME implementation in C# - c#

I am trying to convert some C++ project to C#. I am struggling now with a time class I encountered with C++. It has methods like:
const RsDateTime& RsDateTime::GetTime()
{
FILETIME ft;
::GetSystemTimeAsFileTime(&ft);
::FileTimeToLocalFileTime(&ft, &m_Time); // Why call to local time? What does it do?
return *this;
}
FILETIME RsDateTime::GetUTCTimeAsFile() const
{
FILETIME ft;
::LocalFileTimeToFileTime(&m_Time, &ft); // Why call to local time?
return ft;
}
static unsigned __int64 GetAsUINT64(const FILETIME* ft)
{
ULARGE_INTEGER li;
li.LowPart = ft->dwLowDateTime;
li.HighPart = ft->dwHighDateTime;
return li.QuadPart;
}
Can someone please help me how to approach converting this to C#? Which methods do I need to use? Also what is the difference between FileTime and LocalFileTime as mentioned above?

In Win32 (which this code seems to be), FILETIME is:
A 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
Unless you're dependent on the 1601 epoch, in C#/.NET just use the DateTime type, which contains:
The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001.
My advice is to completely ditch/disregard the C++ code UNLESS you know the data it's returning is being used somewhere that depends on Win32 FILETIME specifically, if not, remove the code and use System.DateTime.

The DateTime C# class now has a method FromFileTime which converts the 64bit FILETIME structure into a DataTime object. At that point, you can use all the DateTime methods and properties normally in c#.
Int64 exampleTime = 0x01cff7924ade4400L;
DateTime dtModified = DateTime.FromFileTime(exampleTime);

Related

How to convert a string formatted like 2018-12-27T02:23:29 to Unix Timestamp in C#

I'm assuming I should just parse the string into a DateTime and go from there... But is there a better way of doing this?
You can use the DateTimeOffset struct, which has a ToUnixTimeSeconds (or ToUnixTimeMilliseconds) method you can use:
long unixTimestamp = DateTimeOffset.Parse("2018-12-27T02:23:29").ToUnixTimeSeconds();
If you're curious how it's done, the source is here: https://referencesource.microsoft.com/#mscorlib/system/datetimeoffset.cs,8e1e87bf153c720e
You should parse it to a normal DateTime object using something from the DateTime.Parse/ParseExact family of functions, and then call a method like this:
public int ToUnixTime(DateTime d)
{
var epoch = new DateTime(1970,1,1);
return (int)(d - epoch).TotalSeconds;
}
DateTime interally stores the "Ticks" (a invented Time unit) since "12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001), in the Gregorian calendar". As a Int64/Long Number. DateTime thus beats UnixTime easily in possible values. Converting to DateTime should be lossless.
Any ToString() call, any other Property call will simply calculate the values based on those Ticks (and culture/Timezone settings for ToString()). Everything else is just a interpretation of the Tick value.
You should parse to DateTime. And getting from Ticks to something as inprecise as the UnixTime is easy math. See Joels Answer for that.
Do note however the DateTimes preccision and accuaracy do not match fully: https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/ DateTime.Now will usually give you only return values in 18 ms steps. And even the Stopwatch has issues with values < 1 ms.

Working with daylight saving time with the DateTime class

I'm in the process of porting a C++ program to C#. The program needs to be able to read a file's "modified" timestamp and store it in a List. This is what I have so far:
C# code:
ret = new List<Byte>(); //list to store the timestamp
var file = new FileInfo(filename);
//Get revision date/time
DateTime revTime_lastWriteTime_LT = file.LastWriteTime;
//Copy date/time into the List (binary buffer)
ret.Add(Convert.ToByte(revTime_lastWriteTime_LT.Month));
ret.Add(Convert.ToByte(revTime_lastWriteTime_LT.Day));
ret.Add(Convert.ToByte(revTime_lastWriteTime_LT.Year % 100)); // 2-digit year
ret.Add(Convert.ToByte(revTime_lastWriteTime_LT.Hour));
ret.Add(Convert.ToByte(revTime_lastWriteTime_LT.Minute));
ret.Add(Convert.ToByte(revTime_lastWriteTime_LT.Second));
The problem occurs when I read in the Hours value. If the file was modified during daylight savings time (like a summer month), the hour value in the C++ program gets subtracted by one. I can't seem to replicate this in my program. In the MSDN article for DateTime it says under "DateTime values": "local time is optionally affected by daylight saving time, which adds or subtracts an hour from the length of a day". In my C# code I made sure to change my DateTime object to local time using, ToLocalTime(), but apparently I haven't instituted the option that the article is talking about. How do I make sure that my DateTime object in local time subtracts a value when reading in a file that was modified during daylight savings time?
C++ code just in case:
static WIN32_FILE_ATTRIBUTE_DATA get_file_data(const std::string & filename)
{
WIN32_FILE_ATTRIBUTE_DATA ret;
if (!GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &ret))
RaiseLastWin32Error();
return ret;
}
//---------------------------------------------------------------------------
static SYSTEMTIME get_file_time(const std::string & filename)
{
const WIN32_FILE_ATTRIBUTE_DATA data(get_file_data(filename));
FILETIME local;
if (!FileTimeToLocalFileTime(&data.ftLastWriteTime, &local))
RaiseLastWin32Error();
SYSTEMTIME ret;
if (!FileTimeToSystemTime(&local, &ret))
RaiseLastWin32Error();
return ret;
}
void parse_asm()
{
// Get revision date/time and size
const SYSTEMTIME rev = get_file_time(filename);
// Copy date/time into the binary buffer
ret.push_back(rev.wMonth);
ret.push_back(rev.wDay);
ret.push_back(rev.wYear % 100); // 2-digit year
ret.push_back(rev.wHour);
ret.push_back(rev.wMinute);
ret.push_back(rev.wSecond);
}
Update for clarity:
In Windows time settings I am in (UTC-05:00) Eastern Time (US & Canada). The file was last modified on Tues Sept 03, 2013 at 12:13:52 PM. The C++ app shows the hour value as 11 and the C# app shows the hour value as 12 using the code above. I need the C# app to show the same hour value as the C++ app.
The bug is actually not with .NET, but with your C++ code. You're using FileTimeToLocalFileTime, which has a well known bug, as described in KB932955:
Note The FileTimeToLocalFileTime() function and the
LocalFileTimeToFileTime() function perform the conversion between UTC
time and local time by using only the current time zone information
and the DST information. This conversion occurs regardless of the
timestamp that is being converted.
So in the example you gave, Sept 03, 2013 at 12:13:52 PM in the US Eastern Time zone should indeed be in daylight saving time. But because it is right now (February 2015) not daylight saving time, you currently get 11 for the hour in your C++ program. If you run the exact same C++ code after next month's transition (March 8th 2015), you will then get 12 for the hour.
The fix for the C++ code is described in the remarks section of the MSDN entry for the FileTimeToLocalFileTime function:
To account for daylight saving time when converting a file time to a local time, use the following sequence of functions in place of using FileTimeToLocalFileTime:
FileTimeToSystemTime
SystemTimeToTzSpecificLocalTime
SystemTimeToFileTime
Now that you understand the bug - if you actually wanted to keep that behavior in C# (which I do not recommend), then you would do the following:
TimeSpan currentOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);
DateTime revTime_LastWriteTime_Lt = file.LastWriteTimeUtc.Add(currentOffset);
The better thing to do would just to leave your current code as is (using file.LastWriteTime), and call the bug fixed.
Sorry, you need to use Add not AddHours, Add accepts TimeSpan. So you're looking for:
file.LastWriteTimeUtc.Add(TimeZoneInfo.Local.BaseUtcOffset);

Convert ulong FILETIME to datetime

My program receiving file time in ulong format and I have to convert it to DateTime format. So here is the function I wrote.
public static DateTime fileTimeToDateTime(ulong fileTime)
{
long temp = (long)fileTime;
DateTime dt1 = DateTime.FromFileTime(temp);
return dt1;
}
But for the filetime 2213360000 ,function returns 1/1/1601 12:00:00 AM but the correct should be 4/22/2009 3:28:29 PM So then I used this webpage to convert filetime to human readable time and it gives me the correct value. So it looks something wrong with my function. Then I convert the correct date using this code peace.
string windowsTime = "4/22/2009 3:28:29 PM";
DateTime time = DateTime.Parse(windowsTime);
long ft = time.ToFileTime();
So here output ft is 128848589090000000 and it not the filetime that I got (2213360000). So looks something wrong with the way I think. Any idea?
FromFileTime expects output from Windows' GetFileTime function -- a FILETIME struct. It measures the number of 100-nanosecond intervals since January 1, 1601 (UTC).
2213360000 100-nanosecond intervals is about 0.02 seconds.
The thing to look at now is where you're getting your FILETIME from, or if you misunderstood what the method is made for. Can you update your question with the code feeding your method?
Did you consider the possibility that the converter from your link is broken? If you reduce the number by nine orders of magnitude, enter 2 instead of 2213360000 and let it convert, it still shows April 22, 2009, just few minutes less.
The number does not seem to be FILETIME. It could be unix stamp, seconds since 1970. In that case the date would be Feb 20, 2040, 6:13 AM. FYI in those units today's date is 1407649082.

what is c time_t equivalent for c#

There is a native method from dll written in c which takes a parameter of type time_t.
Is it possible to use C# uint or ulong for this parameter?
I do not think I should say they are equivalent, but you can convert t_time to DateTime in such a way:
int t= 1070390676; // value of time_t in an ordinary integer
System.DateTime dt= new System.DateTime(1970,1,1).AddSeconds(t);
And this example is from How can I convert date-time data in time_t to C# DateTime class format?
I should also say that UInt32 is used for t_time,too.check DateTime to time_t
Depends on how time_t was defined in the Standard C header files the DLL was compiled against.
If time_t is 64-bit, the C# equivalent is long.
If time_t is 32-bit, then it has the Year 2038 bug and you should ask whoever wrote the DLL for a non-buggy version.
According to Wikipedia's article on Time_t you could use a integer (Int32 or Int64)
Unix and POSIX-compliant systems implement time_t as an integer or real-floating type (typically a 32- or 64-bit integer) which represents the number of seconds since the start of the Unix epoch: midnight UTC of January 1, 1970 (not counting leap seconds).
Bastardo's solution did not help me. I was facing an issue with DST, so an additional conversion to local time was required, or the resulting time differed by one hour. This is what I do:
return new DateTime(1970, 1, 1).ToLocalTime().AddSeconds(time_t);

Convert System::DateTime to _timeb

I have a legacy C++-based application that timestamps incoming network traffic using the CRT _ftime() function. The _ftime() function returns a _timeb structure, which has a 32-bit and a 64-bit implementation. We are using the 32-bit implementation, which looks like this:
struct _timeb {
long time; // 4 bytes
unsigned short millitm; // 2 bytes
short timezone; // 2 bytes
short dstflag; // 2 bytes
};
From the MSDN documentation, here is how each field is interpreted:
dstflag - nonzero if daylight savings time is currently in effect for the local time zone (see _tzset for an explanation of how daylight savings time is determined.)
millitm - fraction of a second in milliseconds
time - time in seconds since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC).
timezone - difference in minutes, moving westward, between UTC and local time. The value of timezone is set from the value of the global variable _timezone (see _tzset).
I am re-working the portion of the code that does the timestamping to use C# in .NET 3.5. Timestamps are now generated using the System.DateTime structure, but I still need to convert them back to the _timeb structure so the legacy C++ code can operate on them. Here is how I am doing that in my managed C++ bridge library:
DateTime dateTime = DateTime::UtcNow;
DateTime baseTime(1970, 1, 1, 0, 0, 0, DateTimeKind::Utc);
TimeSpan delta = dateTime - baseTime;
_timeb timestamp;
timestamp.time = delta.TotalSeconds;
timestamp.millitm = dateTime.Millisecond;
timestamp.dstflag = TimeZoneInfo::Local->IsDaylightSavingTime(dateTime) ? 1 : 0;
timestamp.timezone = TimeZoneInfo::Local->BaseUtcOffset.TotalMinutes * -1;
From what I can tell, this appears to reconstruct the _timeb structure as if I had called _ftime() directly, and that's good. The thing is, timestamps are a critical piece of our application, so this has to be right.
My question is two-fold.
Is my algorithm flawed somehow? Does anyone see anything obvious that I've missed? Are there boundary conditions where this won't work right?
Is there a better way to do the conversion? Does .NET have a way to do this in a more straightforward manner?
You're aware of the Y2K38 problem? I assume you checked the sign of .timezone. Avoid the cleverness of using dateTime.Millisecond, that just confuses the next guy. Looks good otherwise.

Categories

Resources