I'm using DirectoryInfo.CreationTime to get the date when the directory is created
however it returns strange date {21/11/1617 0:00:00}
var directoryInfo = new DirectoryInfo("C:\\testFolder");
var lastWriteTime = directoryInfo.LastWriteTime; // correct value
var creationTime = directoryInfo.CreationTime; // Date = {21/11/1617 0:00:00}
var creationTimeUtc = directoryInfo.CreationTimeUtc; // Date = {21/11/1617 0:00:00}
any idea?
In Addition:
The folder located in NAS share, some folders returns the correct value and some not
I did the following tests:
Restart my machine and check that the data and time is set correctly
Run the application from another machine
recreate the application using .NET 4.0 VS2010
Run the application from different OS windows 7
All returns the same value. however if i select folder properties the creation date is set to 2008.
Is this a bug?
I can shed some light on the "strange date".
Windows file times are based off of 1/1/1601.
A file time is a 64-bit value that represents the number of
100-nanosecond intervals that have elapsed since 12:00 A.M. January 1,
1601 Coordinated Universal Time (UTC). The system records file times
when applications create, access, and write to files.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724290(v=vs.85).aspx
It would appear that your file system is reporting a 16 year offset to DirectoryInfo (which inherits from the FileSystemInfo class, which is calling GetFileAttributesEx()).
The .Net wrapper
public DateTime CreationTimeUtc
{
get{
long fileTime = (long)((ulong)this._data.ftCreationTimeHigh << 32 | (ulong)this._data.ftCreationTimeLow);
return DateTime.FromFileTimeUtc(fileTime);
}
}
DateTime.FromFileTimeUtc adds a value equal to 1/1/1601:
long ticks = fileTime + 504911232000000000L;
return new DateTime(ticks, DateTimeKind.Utc);
I can't find any significance to the offset (16 years). It seems too large to be DST errors or leap years, even accumulated over centuries.
I do think it is peculiar that both CreationTime and CreationTimeUtc return exactly the same date (unless your local time is the same as UTC).
The msdn documentation on CreationTime talks about a bunch of issues which could cause this
Check out the Remarks section of this link below
http://msdn.microsoft.com/en-IN/library/system.io.filesysteminfo.creationtime.aspx
It could be a cached value which is not updated. For this you could use the Refresh method. As indicated in the comments, some old platforms also can probably give you trouble.
Related
In trying to convert a DateTimeOffset between two time zones, I've successfully used TimeZoneInfo.ConvertTime(), but I found a case where the conversion doesn't work. That is - conversion between UTC+11.00 and UTC+10:30 which has no effect.
Here is my completely vanilla source:
public static DateTimeOffset ConvertToNewTimeZone(this DateTimeOffset dt, string newTz)
{
var tzi = DeduceTimeZone(newTz); // converts out of proprietary format into std format
var result = TimeZoneInfo.ConvertTime(dt, tzi);
return result;
}
And here's a debug view of the values of my variables.
Notice how the result is still in UTC+11:00. I expected the result to be in 10:30. Can anyone explain why the conversion didn't happen? I'm not aware of any adjustments that might apply.
Because of the daylight saving time (DST), you may know that January is summer in the southern hemisphere where Lord Howe Island is located, if you try to convert a different date in winter, the offset will be 10:30.
var dt = new DateTime(2022, 7, 1);
TimeZoneInfo.ConvertTime(new DateTimeOffset(dt), tzi);
// 22/7/1 02:30:00 +10:30
TimeZoneInfo.GetUtcOffset
Time zone essentials
In the end I narrowed it down when I noticed that the implementation of the TimeZoneInfo in Windows is different from that in Linux and MacOS. My tests were inadvertently comparing local time (debugging on windows) with a different set of time zones (where I was logging from a Docker container running on AKS on Azure, which was a Linux container).
In the end, it appears that my time zone conversion defaulted to UTC, because the System Timezone Database is empty. That is, TimeZoneInfo.GetSystemTimeZones().Count == 0.
Not sure what to do about it, but at least I know now why my code was failing.
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);
I'm trying to get the last modified date of a file in Windows 7 - I just edited it, so in the properties, the Last Modified value is listed as 11/30/2013 4:55 PM.
However, when I access the file using:
DateTime lastMod = File.GetLastWriteTime(file);
I output the value:
MessageBox.Show(lastMod.toString());
This always gives 12/31/1600 6:00:00 PM, regardless of which file I'm working with, regardless of creation time, modification time, etc.
I suspect you're using the wrong file name. The documentation for GetLastWriteTime specifies:
If the file described in the path parameter does not exist, this method returns 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC), adjusted to local time.
As that's the value you're getting, it suggests the file described in the path parameter quite possibly doesn't exist - so you should check the value of file and bear in mind that if it's a relative filename, it might not be relative to the directory you're expecting.
In my web application I am creating folders and files dynamically, while creating Folder/Files CreatedDate or ModifiedDate is taking as Server Time..
I want to set CreatedDate or ModifiedDate as my local time..
how to do this..
My code for creating folders
DirectoryInfo dirDptFolder = new DirectoryInfo(strDptRoot);
if (dirDptFolder.Exists == false)
{
dirDptFolder.Create();
}
The server creation time is the same as your local time
If your clocks are up to date, the creation time on the server will be the same time as your local time.
It may seem different because you may be located in different time zones.
The best way to think of it is that all times are saved as UTC. They are displayed to the local time depending on your time zone settings in your OS.
You can get the actual file creation time in UTC like so:
FileInfo file = new FileInfo(filePath);
creationTimeUTC = file.CreationTimeUtc;
Console.WriteLine("The files creation time in UTC: {0}", file.CreationTimeUtc);
If your local machine is using Central Standard Time then you could convert the files creation time on the server to display as CST time like so:
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(file.CreationTimeUtc, cstZone);
Console.WriteLine("The files creation time in CST: {0}", cstTime);
Therefore it is not necessary to change the creation time on the server to your local time, files are always saved as UTC.
If you want the server time to be exactly the same as your local time, either change your servers TimeZone to match that of your local machine or visa versa.
As long as your file system is NTFS, then file times are always stored as UTC.
If you look at the implementation of System.IO.FileInfo.CreationTime, you will see the following:
public DateTime CreationTime
{
get
{
return this.CreationTimeUtc.ToLocalTime();
}
set
{
this.CreationTimeUtc = value.ToUniversalTime();
}
}
As you can see, it's a wrapper around CreationTimeUtc, just converted to the local time for convenience. The LastWriteTime and LastAccessTime properties work the same way.
So, you can't change a file to be stamped with a different time zone, because they are never stamped with the local time of any particular time zone to begin with. They are stamped in UTC.
If you want to convert that to some other time zone, then do it on the way out when you read it.
FileInfo fi = new FileInfo(path);
DateTime utc = fi.CreationTimeUtc;
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime eastern = TimeZoneInfo.ConvertTimeFromUtc(utc, tzi);
Note, there are similar methods off of the System.IO.File class, such as File.GetCreationTimeUtc(), which essentially do the same thing. Use whichever you are comfortable with.
Also note, this is not the case for FAT/FAT32 file systems. For those file systems, the server's local timestamp is used. Taking a file from one location to another could lead to misinterpreting the timestamp.
What if different users have different time zones? How about just converting to user time when displaying the data to the users? :)
You can either ask the user to input their timezone or detect it using javascript and store it in a cookie. there are various ways to do this, but here is one script that can do it https://bitbucket.org/pellepim/jstimezonedetect
cookies can also be saved in a variety of ways, but I like jquery.
http://plugins.jquery.com/cookie/
You can then read the cookie on the server side and use the methods others have mentioned to convert your times to that timezone.
I am getting the "LastWriteTime" of my executable and comparing it to an internal DateTime that I have set. If the LastWriteTime is less than or equal to the internal DateTime then I will clear two tables from a database.
This code works great for me in the Pacific Time Zone. But if a user is in another time zone, (example 4 hours ahead of me), then it does not work because the "LastWriteTime" returns the time converted to their time zone. For example, I am looking for the value of "12/12/2012 8:38:12 AM" and if they are 4 hours ahead of me, this value gets automatically changed to "12/12/2012 12:38:12 PM" on their systems.
Can someone please show me what I should modify in my code to take into account for different time zones so the "LastWriteTime" and my 'build2023_EXE_Date' variable both return the same Date/Time so my comparision of the two date/time values don't fail regardless of what time zone my end user is in?
I am using .NET 3.5, not .Net 4.x
//http://stackoverflow.com/questions/1600962/displaying-the-build-date
string w_file = "MyEXE.exe";
string w_directory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
Path.DirectorySeparatorChar + "MyEXE";
DateTime currentExeTime = File.GetLastWriteTime(System.IO.Path.Combine(w_directory, w_file));
DateTime build2023_EXE_Date = new DateTime(2012, 12, 12, 8, 38, 12); //"12/12/2012 8:38:12 AM"
//We need to truncate the millisecond time off of the EXE LastWriteTime
//or else when we compare to our internal DateTime build2323_EXE_Date value,
//it will not match
//http://stackoverflow.com/questions/1004698/how-to-truncate-milliseconds-off-of-a-net-datetime
currentExeTime = new DateTime(
currentExeTime.Ticks - (currentExeTime.Ticks % TimeSpan.TicksPerSecond),
currentExeTime.Kind
);
if (currentExeTime <= build2023_EXE_Date) //If previous build matches or is before the Build 2023 date then clear these two tables.
{
//This will fail the comparision if the user is in a different time zone than me.
//Clear tables
}
Unless you've got a specific need to keep dates in local time or have an associated time zone, I suggest you use universal time instead. This makes working with dates far easier because they all compare sanely, and it can actually be more performant (when you request DateTime.Now, .NET calls DateTime.UtcNow and then performs a relatively expensive adjustment to local time).
Another option is to use DateTimeOffset, which stores a date with an offset (not a time zone! -- for instance, DST will give you different offsets) and makes comparisons as easy as a universal DateTime. Unfortunately, though, GetLastWriteTime doesn't use DateTimeOffset so this might not work for you.
Use the DateTime ToUniversalTime() method