1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.build.apkzlib.zip.utils; 18 19 import com.google.common.base.Verify; 20 import java.util.Calendar; 21 import java.util.Date; 22 23 /** 24 * Yes. This actually refers to MS-DOS in 2015. That's all I have to say about legacy stuff. 25 */ 26 public class MsDosDateTimeUtils { 27 /** 28 * Utility class: no constructor. 29 */ MsDosDateTimeUtils()30 private MsDosDateTimeUtils() { 31 } 32 33 /** 34 * Packs java time value into an MS-DOS time value. 35 * 36 * @param time the time value 37 * @return the MS-DOS packed time 38 */ packTime(long time)39 public static int packTime(long time) { 40 Calendar c = Calendar.getInstance(); 41 c.setTime(new Date(time)); 42 43 int seconds = c.get(Calendar.SECOND); 44 int minutes = c.get(Calendar.MINUTE); 45 int hours = c.get(Calendar.HOUR_OF_DAY); 46 47 /* 48 * Here is how MS-DOS packs a time value: 49 * 0-4: seconds (divided by 2 because we only have 5 bits = 32 different numbers) 50 * 5-10: minutes (6 bits = 64 possible values) 51 * 11-15: hours (5 bits = 32 possible values) 52 * 53 * source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724247(v=vs.85).aspx 54 */ 55 return (hours << 11) | (minutes << 5) | (seconds / 2); 56 } 57 58 /** 59 * Packs the current time value into an MS-DOS time value. 60 * 61 * @return the MS-DOS packed time 62 */ packCurrentTime()63 public static int packCurrentTime() { 64 return packTime(new Date().getTime()); 65 } 66 67 /** 68 * Packs java time value into an MS-DOS date value. 69 * 70 * @param time the time value 71 * @return the MS-DOS packed date 72 */ packDate(long time)73 public static int packDate(long time) { 74 Calendar c = Calendar.getInstance(); 75 c.setTime(new Date(time)); 76 77 /* 78 * Even MS-DOS used 1 for January. Someone wasn't really thinking when they decided on Java 79 * it would start at 0... 80 */ 81 int day = c.get(Calendar.DAY_OF_MONTH); 82 int month = c.get(Calendar.MONTH) + 1; 83 84 /* 85 * MS-DOS counts years starting from 1980. Since its launch date was in 81, it was obviously 86 * not necessary to talk about dates earlier than that. 87 */ 88 int year = c.get(Calendar.YEAR) - 1980; 89 Verify.verify(year >= 0 && year < 128); 90 91 /* 92 * Here is how MS-DOS packs a date value: 93 * 0-4: day (5 bits = 32 values) 94 * 5-8: month (4 bits = 16 values) 95 * 9-15: year (7 bits = 128 values) 96 * 97 * source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724247(v=vs.85).aspx 98 */ 99 return (year << 9) | (month << 5) | day; 100 } 101 102 /** 103 * Packs the current time value into an MS-DOS date value. 104 * 105 * @return the MS-DOS packed date 106 */ packCurrentDate()107 public static int packCurrentDate() { 108 return packDate(new Date().getTime()); 109 } 110 } 111