The DotNetZip library sets the LastModified value for an entry, equal to the Last Modified time of the file in the filesystem. If an entry is added from a stream, the library uses System.DateTime.Now for this value, for the given entry.
This property allows the application to retrieve and possibly set the LastModified value on an entry, to an arbitrary value. DateTime values with a DateTimeKind setting of DateTimeKind.Unspecified are taken to be expressed as DateTimeKind.Local.
Be aware that because of the way PKWare's Zip specification describes how times are stored in the zip file, the full precision of the System.DateTime datatype is not stored for the last modified time when saving zip files. For more information on how times are formatted, see the PKZip specification.
The actual last modified time of a file can be stored in multiple ways in the zip file, and they are not mutually exclusive:
- In the so-called "DOS" format, which has a 2-second precision. Values are rounded to the nearest even second. For example, if the time on the file is 12:34:43, then it will be stored as 12:34:44. This first value is accessible via the LastModified property. This value is always present in the metadata for each zip entry. In some cases the value is invalid, or zero.
- In the so-called "Windows" or "NTFS" format, as an 8-byte integer quantity expressed as the number of 1/10 milliseconds (in other words the number of 100 nanosecond units) since January 1, 1601 (UTC). This format is how Windows represents file times. This time is accessible via the ModifiedTime property.
- In the "Unix" format, a 4-byte quantity specifying the number of seconds since January 1, 1970 UTC.
- In an older format, now deprecated but still used by some current tools. This format is also a 4-byte quantity specifying the number of seconds since January 1, 1970 UTC.
Zip tools and libraries will always at least handle (read or write) the DOS time, and may also handle the other time formats. Keep in mind that while the names refer to particular operating systems, there is nothing in the time formats themselves that prevents their use on other operating systems.
When reading ZIP files, the DotNetZip library reads the Windows-formatted time, if it is stored in the entry, and sets both LastModified and ModifiedTime to that value. When writing ZIP files, the DotNetZip library by default will write both time quantities. It can also emit the Unix-formatted time if desired (See EmitTimesInUnixFormatWhenSaving.)
The last modified time of the file created upon a call to ZipEntry.Extract() may be adjusted during extraction to compensate for differences in how the .NET Base Class Library deals with daylight saving time (DST) versus how the Windows filesystem deals with daylight saving time. Raymond Chen provides some good context.
In a nutshell: Daylight savings time rules change regularly. In 2007, for example, the inception week of DST changed. In 1977, DST was in place all year round. In 1945, likewise. And so on. Win32 does not attempt to guess which time zone rules were in effect at the time in question. It will render a time as "standard time" and allow the app to change to DST as necessary. .NET makes a different choice.
Compare the output of FileInfo.LastWriteTime.ToString("f") with what you see in the Windows Explorer property sheet for a file that was last written to on the other side of the DST transition. For example, suppose the file was last modified on October 17, 2003, during DST but DST is not currently in effect. Explorer's file properties reports Thursday, October 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17, 2003, 9:45 AM.
Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific STANDARD Time. Even though October 17 of that year occurred during Pacific Daylight Time, Win32 displays the time as standard time because that's what time it is NOW.
.NET BCL assumes that the current DST rules were in place at the time in question. So, .NET says, "Well, if the rules in effect now were also in effect on October 17, 2003, then that would be daylight time" so it displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time.
So .NET gives a value which is more intuitively correct, but is also potentially incorrect, and which is not invertible. Win32 gives a value which is intuitively incorrect, but is strictly correct.
Because of this funkiness, this library adds one hour to the LastModified time on the extracted file, if necessary. That is to say, if the time in question had occurred in what the .NET Base Class Library assumed to be DST. This assumption may be wrong given the constantly changing DST rules, but it is the best we can do.