@@ -238,7 +238,7 @@ public ZipEntry(ZipEntry entry)
238238 size = entry . size ;
239239 compressedSize = entry . compressedSize ;
240240 crc = entry . crc ;
241- dosTime = entry . dosTime ;
241+ dateTime = entry . DateTime ;
242242 method = entry . method ;
243243 comment = entry . comment ;
244244 versionToExtract = entry . versionToExtract ;
@@ -696,18 +696,54 @@ public long DosTime
696696 }
697697 else
698698 {
699- return dosTime ;
699+ var year = ( uint ) DateTime . Year ;
700+ var month = ( uint ) DateTime . Month ;
701+ var day = ( uint ) DateTime . Day ;
702+ var hour = ( uint ) DateTime . Hour ;
703+ var minute = ( uint ) DateTime . Minute ;
704+ var second = ( uint ) DateTime . Second ;
705+
706+ if ( year < 1980 )
707+ {
708+ year = 1980 ;
709+ month = 1 ;
710+ day = 1 ;
711+ hour = 0 ;
712+ minute = 0 ;
713+ second = 0 ;
714+ }
715+ else if ( year > 2107 )
716+ {
717+ year = 2107 ;
718+ month = 12 ;
719+ day = 31 ;
720+ hour = 23 ;
721+ minute = 59 ;
722+ second = 59 ;
723+ }
724+
725+ return ( ( year - 1980 ) & 0x7f ) << 25 |
726+ ( month << 21 ) |
727+ ( day << 16 ) |
728+ ( hour << 11 ) |
729+ ( minute << 5 ) |
730+ ( second >> 1 ) ;
700731 }
701732 }
702733
703734 set
704735 {
705736 unchecked
706737 {
707- dosTime = ( uint ) value ;
738+ var dosTime = ( uint ) value ;
739+ uint sec = Math . Min ( 59 , 2 * ( dosTime & 0x1f ) ) ;
740+ uint min = Math . Min ( 59 , ( dosTime >> 5 ) & 0x3f ) ;
741+ uint hrs = Math . Min ( 23 , ( dosTime >> 11 ) & 0x1f ) ;
742+ uint mon = Math . Max ( 1 , Math . Min ( 12 , ( ( uint ) ( value >> 21 ) & 0xf ) ) ) ;
743+ uint year = ( ( dosTime >> 25 ) & 0x7f ) + 1980 ;
744+ int day = Math . Max ( 1 , Math . Min ( DateTime . DaysInMonth ( ( int ) year , ( int ) mon ) , ( int ) ( ( value >> 16 ) & 0x1f ) ) ) ;
745+ DateTime = new DateTime ( ( int ) year , ( int ) mon , day , ( int ) hrs , ( int ) min , ( int ) sec , DateTimeKind . Utc ) ;
708746 }
709-
710- known |= Known . Time ;
711747 }
712748 }
713749
@@ -721,49 +757,13 @@ public DateTime DateTime
721757 {
722758 get
723759 {
724- uint sec = Math . Min ( 59 , 2 * ( dosTime & 0x1f ) ) ;
725- uint min = Math . Min ( 59 , ( dosTime >> 5 ) & 0x3f ) ;
726- uint hrs = Math . Min ( 23 , ( dosTime >> 11 ) & 0x1f ) ;
727- uint mon = Math . Max ( 1 , Math . Min ( 12 , ( ( dosTime >> 21 ) & 0xf ) ) ) ;
728- uint year = ( ( dosTime >> 25 ) & 0x7f ) + 1980 ;
729- int day = Math . Max ( 1 , Math . Min ( DateTime . DaysInMonth ( ( int ) year , ( int ) mon ) , ( int ) ( ( dosTime >> 16 ) & 0x1f ) ) ) ;
730- return new System . DateTime ( ( int ) year , ( int ) mon , day , ( int ) hrs , ( int ) min , ( int ) sec ) ;
760+ return dateTime ;
731761 }
732762
733763 set
734764 {
735- var year = ( uint ) value . Year ;
736- var month = ( uint ) value . Month ;
737- var day = ( uint ) value . Day ;
738- var hour = ( uint ) value . Hour ;
739- var minute = ( uint ) value . Minute ;
740- var second = ( uint ) value . Second ;
741-
742- if ( year < 1980 )
743- {
744- year = 1980 ;
745- month = 1 ;
746- day = 1 ;
747- hour = 0 ;
748- minute = 0 ;
749- second = 0 ;
750- }
751- else if ( year > 2107 )
752- {
753- year = 2107 ;
754- month = 12 ;
755- day = 31 ;
756- hour = 23 ;
757- minute = 59 ;
758- second = 59 ;
759- }
760-
761- DosTime = ( ( year - 1980 ) & 0x7f ) << 25 |
762- ( month << 21 ) |
763- ( day << 16 ) |
764- ( hour << 11 ) |
765- ( minute << 5 ) |
766- ( second >> 1 ) ;
765+ dateTime = value ;
766+ known |= Known . Time ;
767767 }
768768 }
769769
@@ -1088,14 +1088,14 @@ internal void ProcessExtraData(bool localHeader)
10881088 }
10891089 }
10901090
1091- DateTime = GetDateTime ( extraData ) ;
1091+ DateTime = GetDateTime ( extraData ) ?? DateTime ;
10921092 if ( method == CompressionMethod . WinZipAES )
10931093 {
10941094 ProcessAESExtraData ( extraData ) ;
10951095 }
10961096 }
10971097
1098- private DateTime GetDateTime ( ZipExtraData extraData )
1098+ private DateTime ? GetDateTime ( ZipExtraData extraData )
10991099 {
11001100 // Check for NT timestamp
11011101 // NOTE: Disable by default to match behavior of InfoZIP
@@ -1107,22 +1107,10 @@ private DateTime GetDateTime(ZipExtraData extraData)
11071107
11081108 // Check for Unix timestamp
11091109 ExtendedUnixData unixData = extraData . GetData < ExtendedUnixData > ( ) ;
1110- if ( unixData != null &&
1111- // Only apply modification time, but require all other values to be present
1112- // This is done to match InfoZIP's behaviour
1113- ( ( unixData . Include & ExtendedUnixData . Flags . ModificationTime ) != 0 ) &&
1114- ( ( unixData . Include & ExtendedUnixData . Flags . AccessTime ) != 0 ) &&
1115- ( ( unixData . Include & ExtendedUnixData . Flags . CreateTime ) != 0 ) )
1110+ if ( unixData != null && unixData . Include . HasFlag ( ExtendedUnixData . Flags . ModificationTime ) )
11161111 return unixData . ModificationTime ;
11171112
1118- // Fall back to DOS time
1119- uint sec = Math . Min ( 59 , 2 * ( dosTime & 0x1f ) ) ;
1120- uint min = Math . Min ( 59 , ( dosTime >> 5 ) & 0x3f ) ;
1121- uint hrs = Math . Min ( 23 , ( dosTime >> 11 ) & 0x1f ) ;
1122- uint mon = Math . Max ( 1 , Math . Min ( 12 , ( ( dosTime >> 21 ) & 0xf ) ) ) ;
1123- uint year = ( ( dosTime >> 25 ) & 0x7f ) + 1980 ;
1124- int day = Math . Max ( 1 , Math . Min ( DateTime . DaysInMonth ( ( int ) year , ( int ) mon ) , ( int ) ( ( dosTime >> 16 ) & 0x1f ) ) ) ;
1125- return new DateTime ( ( int ) year , ( int ) mon , day , ( int ) hrs , ( int ) min , ( int ) sec , DateTimeKind . Utc ) ;
1113+ return null ;
11261114 }
11271115
11281116 // For AES the method in the entry is 99, and the real compression method is in the extradata
@@ -1328,7 +1316,7 @@ public static string CleanName(string name)
13281316 private ulong compressedSize ;
13291317 private ushort versionToExtract ; // Version required to extract (library handles <= 2.0)
13301318 private uint crc ;
1331- private uint dosTime ;
1319+ private DateTime dateTime ;
13321320
13331321 private CompressionMethod method = CompressionMethod . Deflated ;
13341322 private byte [ ] extra ;
0 commit comments