Read the time of a JarEntryData using MSDOS Date Time format
The format is rather unusual. The time is 16 bits: 5 bits for the hour, 6 bits for the minutes, and 5 bits for the seconds. 5 bits only allows 32 values (0-31) so the number must be doubled, meaning that the time is only accurate to the nearest two seconds. Also, the JDK rounds this down by subtracting one. The doubling and rounding is performed by shifting one place to the left and masking off the right-most bit respectively. The date is 16 bits: 7 bits for the year, 4 bits for the month, and 5 bits for the day. The year is from 1980, i.e. the earliest date that can be represented is 1980-01-01. See http://mindprod.com/jgloss/zip.html for more details of the format. Fixes gh-2826
This commit is contained in:
parent
764e34b9db
commit
ebb8d0c55f
|
@ -19,6 +19,7 @@ package org.springframework.boot.loader.jar;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
|
@ -145,7 +146,20 @@ public final class JarEntryData {
|
|||
}
|
||||
|
||||
public long getTime() {
|
||||
return Bytes.littleEndianValue(this.header, 12, 4);
|
||||
long time = Bytes.littleEndianValue(this.header, 12, 2);
|
||||
|
||||
int seconds = (int) ((time << 1) & 0x3E);
|
||||
int minutes = (int) ((time >> 5) & 0x3F);
|
||||
int hours = (int) ((time >> 11) & 0x1F);
|
||||
|
||||
long date = Bytes.littleEndianValue(this.header, 14, 2);
|
||||
|
||||
int day = (int) (date & 0x1F);
|
||||
int month = (int) ((date >> 5) & 0xF) - 1;
|
||||
int year = (int) ((date >> 9) & 0x7F) + 1980;
|
||||
|
||||
return new GregorianCalendar(year, month, day, hours, minutes, seconds)
|
||||
.getTimeInMillis();
|
||||
}
|
||||
|
||||
public long getCrc() {
|
||||
|
|
|
@ -170,6 +170,14 @@ public class JarFileTests {
|
|||
assertThat(this.jarFile.size(), equalTo((int) this.rootJarFile.length()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntryTime() throws Exception {
|
||||
java.util.jar.JarFile jdkJarFile = new java.util.jar.JarFile(this.rootJarFile);
|
||||
assertThat(this.jarFile.getEntry("META-INF/MANIFEST.MF").getTime(),
|
||||
equalTo(jdkJarFile.getEntry("META-INF/MANIFEST.MF").getTime()));
|
||||
jdkJarFile.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close() throws Exception {
|
||||
RandomAccessDataFile randomAccessDataFile = spy(new RandomAccessDataFile(
|
||||
|
|
Loading…
Reference in New Issue