DateTimeConverter.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. namespace PhpZip\Util;
  3. use PhpZip\Exception\ZipException;
  4. /**
  5. * Convert unix timestamp values to DOS date/time values and vice versa.
  6. *
  7. * @author Ne-Lexa alexey@nelexa.ru
  8. * @license MIT
  9. */
  10. class DateTimeConverter
  11. {
  12. /**
  13. * Smallest supported DOS date/time value in a ZIP file,
  14. * which is January 1st, 1980 AD 00:00:00 local time.
  15. */
  16. const MIN_DOS_TIME = 0x210000; // (1 << 21) | (1 << 16)
  17. /**
  18. * Largest supported DOS date/time value in a ZIP file,
  19. * which is December 31st, 2107 AD 23:59:58 local time.
  20. */
  21. const MAX_DOS_TIME = 0xff9fbf7d; // ((2107 - 1980) << 25) | (12 << 21) | (31 << 16) | (23 << 11) | (59 << 5) | (58 >> 1);
  22. /**
  23. * Convert a 32 bit integer DOS date/time value to a UNIX timestamp value.
  24. *
  25. * @param int $dosTime Dos date/time
  26. *
  27. * @return int Unix timestamp
  28. */
  29. public static function toUnixTimestamp($dosTime)
  30. {
  31. if ($dosTime < self::MIN_DOS_TIME) {
  32. $dosTime = self::MIN_DOS_TIME;
  33. } elseif ($dosTime > self::MAX_DOS_TIME) {
  34. $dosTime = self::MAX_DOS_TIME;
  35. }
  36. return mktime(
  37. ($dosTime >> 11) & 0x1f, // hour
  38. ($dosTime >> 5) & 0x3f, // minute
  39. 2 * ($dosTime & 0x1f), // second
  40. ($dosTime >> 21) & 0x0f, // month
  41. ($dosTime >> 16) & 0x1f, // day
  42. 1980 + (($dosTime >> 25) & 0x7f) // year
  43. );
  44. }
  45. /**
  46. * Converts a UNIX timestamp value to a DOS date/time value.
  47. *
  48. * @param int $unixTimestamp the number of seconds since midnight, January 1st,
  49. * 1970 AD UTC
  50. *
  51. * @throws ZipException if unix timestamp is negative
  52. *
  53. * @return int a DOS date/time value reflecting the local time zone and
  54. * rounded down to even seconds
  55. * and is in between DateTimeConverter::MIN_DOS_TIME and DateTimeConverter::MAX_DOS_TIME
  56. */
  57. public static function toDosTime($unixTimestamp)
  58. {
  59. if ($unixTimestamp < 0) {
  60. throw new ZipException('Negative unix timestamp: ' . $unixTimestamp);
  61. }
  62. $date = getdate($unixTimestamp);
  63. if ($date['year'] < 1980) {
  64. return self::MIN_DOS_TIME;
  65. }
  66. $date['year'] -= 1980;
  67. return $date['year'] << 25 | $date['mon'] << 21 |
  68. $date['mday'] << 16 | $date['hours'] << 11 |
  69. $date['minutes'] << 5 | $date['seconds'] >> 1;
  70. }
  71. }