PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/phpoffice/phpexcel/Classes/PHPExcel/Shared/Date.php

https://gitlab.com/techniconline/kmc
PHP | 409 lines | 221 code | 45 blank | 143 comment | 40 complexity | 5ae20b3fda0663a99171e5f740636ce9 MD5 | raw file
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2014 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Shared
  23. * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. /**
  28. * PHPExcel_Shared_Date
  29. *
  30. * @category PHPExcel
  31. * @package PHPExcel_Shared
  32. * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
  33. */
  34. class PHPExcel_Shared_Date
  35. {
  36. /** constants */
  37. const CALENDAR_WINDOWS_1900 = 1900; // Base date of 1st Jan 1900 = 1.0
  38. const CALENDAR_MAC_1904 = 1904; // Base date of 2nd Jan 1904 = 1.0
  39. /*
  40. * Names of the months of the year, indexed by shortname
  41. * Planned usage for locale settings
  42. *
  43. * @public
  44. * @var string[]
  45. */
  46. public static $_monthNames = array('Jan' => 'January',
  47. 'Feb' => 'February',
  48. 'Mar' => 'March',
  49. 'Apr' => 'April',
  50. 'May' => 'May',
  51. 'Jun' => 'June',
  52. 'Jul' => 'July',
  53. 'Aug' => 'August',
  54. 'Sep' => 'September',
  55. 'Oct' => 'October',
  56. 'Nov' => 'November',
  57. 'Dec' => 'December',
  58. );
  59. /*
  60. * Names of the months of the year, indexed by shortname
  61. * Planned usage for locale settings
  62. *
  63. * @public
  64. * @var string[]
  65. */
  66. public static $_numberSuffixes = array('st',
  67. 'nd',
  68. 'rd',
  69. 'th',
  70. );
  71. /*
  72. * Base calendar year to use for calculations
  73. *
  74. * @private
  75. * @var int
  76. */
  77. protected static $_excelBaseDate = self::CALENDAR_WINDOWS_1900;
  78. /**
  79. * Set the Excel calendar (Windows 1900 or Mac 1904)
  80. *
  81. * @param integer $baseDate Excel base date (1900 or 1904)
  82. * @return boolean Success or failure
  83. */
  84. public static function setExcelCalendar($baseDate)
  85. {
  86. if (($baseDate == self::CALENDAR_WINDOWS_1900) ||
  87. ($baseDate == self::CALENDAR_MAC_1904)
  88. ) {
  89. self::$_excelBaseDate = $baseDate;
  90. return TRUE;
  91. }
  92. return FALSE;
  93. } // function setExcelCalendar()
  94. /**
  95. * Return the Excel calendar (Windows 1900 or Mac 1904)
  96. *
  97. * @return integer Excel base date (1900 or 1904)
  98. */
  99. public static function getExcelCalendar()
  100. {
  101. return self::$_excelBaseDate;
  102. } // function getExcelCalendar()
  103. /**
  104. * Convert a date from Excel to PHP
  105. *
  106. * @param long $dateValue Excel date/time value
  107. * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as
  108. * a UST timestamp, or adjusted to UST
  109. * @param string $timezone The timezone for finding the adjustment from UST
  110. * @return long PHP serialized date/time
  111. */
  112. public static function ExcelToPHP($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL)
  113. {
  114. if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) {
  115. $my_excelBaseDate = 25569;
  116. // Adjust for the spurious 29-Feb-1900 (Day 60)
  117. if ($dateValue < 60) {
  118. --$my_excelBaseDate;
  119. }
  120. } else {
  121. $my_excelBaseDate = 24107;
  122. }
  123. // Perform conversion
  124. if ($dateValue >= 1) {
  125. $utcDays = $dateValue - $my_excelBaseDate;
  126. $returnValue = round($utcDays * 86400);
  127. if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) {
  128. $returnValue = (integer)$returnValue;
  129. }
  130. } else {
  131. $hours = round($dateValue * 24);
  132. $mins = round($dateValue * 1440) - round($hours * 60);
  133. $secs = round($dateValue * 86400) - round($hours * 3600) - round($mins * 60);
  134. $returnValue = (integer)gmmktime($hours, $mins, $secs);
  135. }
  136. $timezoneAdjustment = ($adjustToTimezone) ?
  137. PHPExcel_Shared_TimeZone::getTimezoneAdjustment($timezone, $returnValue) :
  138. 0;
  139. // Return
  140. return $returnValue + $timezoneAdjustment;
  141. } // function ExcelToPHP()
  142. /**
  143. * Convert a date from Excel to a PHP Date/Time object
  144. *
  145. * @param integer $dateValue Excel date/time value
  146. * @return DateTime PHP date/time object
  147. */
  148. public static function ExcelToPHPObject($dateValue = 0)
  149. {
  150. $dateTime = self::ExcelToPHP($dateValue);
  151. $days = floor($dateTime / 86400);
  152. $time = round((($dateTime / 86400) - $days) * 86400);
  153. $hours = round($time / 3600);
  154. $minutes = round($time / 60) - ($hours * 60);
  155. $seconds = round($time) - ($hours * 3600) - ($minutes * 60);
  156. $dateObj = date_create('1-Jan-1970+' . $days . ' days');
  157. $dateObj->setTime($hours, $minutes, $seconds);
  158. return $dateObj;
  159. } // function ExcelToPHPObject()
  160. /**
  161. * Convert a date from PHP to Excel
  162. *
  163. * @param mixed $dateValue PHP serialized date/time or date object
  164. * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as
  165. * a UST timestamp, or adjusted to UST
  166. * @param string $timezone The timezone for finding the adjustment from UST
  167. * @return mixed Excel date/time value
  168. * or boolean FALSE on failure
  169. */
  170. public static function PHPToExcel($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL)
  171. {
  172. $saveTimeZone = date_default_timezone_get();
  173. date_default_timezone_set('UTC');
  174. $retValue = FALSE;
  175. if ((is_object($dateValue)) && ($dateValue instanceof DateTime)) {
  176. $retValue = self::FormattedPHPToExcel($dateValue->format('Y'), $dateValue->format('m'), $dateValue->format('d'),
  177. $dateValue->format('H'), $dateValue->format('i'), $dateValue->format('s')
  178. );
  179. } elseif (is_numeric($dateValue)) {
  180. $retValue = self::FormattedPHPToExcel(date('Y', $dateValue), date('m', $dateValue), date('d', $dateValue),
  181. date('H', $dateValue), date('i', $dateValue), date('s', $dateValue)
  182. );
  183. }
  184. date_default_timezone_set($saveTimeZone);
  185. return $retValue;
  186. } // function PHPToExcel()
  187. /**
  188. * FormattedPHPToExcel
  189. *
  190. * @param long $year
  191. * @param long $month
  192. * @param long $day
  193. * @param long $hours
  194. * @param long $minutes
  195. * @param long $seconds
  196. * @return long Excel date/time value
  197. */
  198. public static function FormattedPHPToExcel($year, $month, $day, $hours = 0, $minutes = 0, $seconds = 0)
  199. {
  200. if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) {
  201. //
  202. // Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel
  203. // This affects every date following 28th February 1900
  204. //
  205. $excel1900isLeapYear = TRUE;
  206. if (($year == 1900) && ($month <= 2)) {
  207. $excel1900isLeapYear = FALSE;
  208. }
  209. $my_excelBaseDate = 2415020;
  210. } else {
  211. $my_excelBaseDate = 2416481;
  212. $excel1900isLeapYear = FALSE;
  213. }
  214. // Julian base date Adjustment
  215. if ($month > 2) {
  216. $month -= 3;
  217. } else {
  218. $month += 9;
  219. --$year;
  220. }
  221. // Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0)
  222. $century = substr($year, 0, 2);
  223. $decade = substr($year, 2, 2);
  224. $excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $my_excelBaseDate + $excel1900isLeapYear;
  225. $excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400;
  226. return (float)$excelDate + $excelTime;
  227. } // function FormattedPHPToExcel()
  228. /**
  229. * Is a given cell a date/time?
  230. *
  231. * @param PHPExcel_Cell $pCell
  232. * @return boolean
  233. */
  234. public static function isDateTime(PHPExcel_Cell $pCell)
  235. {
  236. return self::isDateTimeFormat(
  237. $pCell->getWorksheet()->getStyle(
  238. $pCell->getCoordinate()
  239. )->getNumberFormat()
  240. );
  241. } // function isDateTime()
  242. /**
  243. * Is a given number format a date/time?
  244. *
  245. * @param PHPExcel_Style_NumberFormat $pFormat
  246. * @return boolean
  247. */
  248. public static function isDateTimeFormat(PHPExcel_Style_NumberFormat $pFormat)
  249. {
  250. return self::isDateTimeFormatCode($pFormat->getFormatCode());
  251. } // function isDateTimeFormat()
  252. private static $possibleDateFormatCharacters = 'eymdHs';
  253. /**
  254. * Is a given number format code a date/time?
  255. *
  256. * @param string $pFormatCode
  257. * @return boolean
  258. */
  259. public static function isDateTimeFormatCode($pFormatCode = '')
  260. {
  261. if (strtolower($pFormatCode) === strtolower(PHPExcel_Style_NumberFormat::FORMAT_GENERAL))
  262. // "General" contains an epoch letter 'e', so we trap for it explicitly here (case-insensitive check)
  263. return FALSE;
  264. if (preg_match('/[0#]E[+-]0/i', $pFormatCode))
  265. // Scientific format
  266. return FALSE;
  267. // Switch on formatcode
  268. switch ($pFormatCode) {
  269. // Explicitly defined date formats
  270. case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD:
  271. case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2:
  272. case PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY:
  273. case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYSLASH:
  274. case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYMINUS:
  275. case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMMINUS:
  276. case PHPExcel_Style_NumberFormat::FORMAT_DATE_MYMINUS:
  277. case PHPExcel_Style_NumberFormat::FORMAT_DATE_DATETIME:
  278. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME1:
  279. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME2:
  280. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3:
  281. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4:
  282. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME5:
  283. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME6:
  284. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME7:
  285. case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME8:
  286. case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDDSLASH:
  287. case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14:
  288. case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15:
  289. case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX16:
  290. case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX17:
  291. case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX22:
  292. return TRUE;
  293. }
  294. // Typically number, currency or accounting (or occasionally fraction) formats
  295. if ((substr($pFormatCode, 0, 1) == '_') || (substr($pFormatCode, 0, 2) == '0 ')) {
  296. return FALSE;
  297. }
  298. // Try checking for any of the date formatting characters that don't appear within square braces
  299. if (preg_match('/(^|\])[^\[]*[' . self::$possibleDateFormatCharacters . ']/i', $pFormatCode)) {
  300. // We might also have a format mask containing quoted strings...
  301. // we don't want to test for any of our characters within the quoted blocks
  302. if (strpos($pFormatCode, '"') !== FALSE) {
  303. $segMatcher = FALSE;
  304. foreach (explode('"', $pFormatCode) as $subVal) {
  305. // Only test in alternate array entries (the non-quoted blocks)
  306. if (($segMatcher = !$segMatcher) &&
  307. (preg_match('/(^|\])[^\[]*[' . self::$possibleDateFormatCharacters . ']/i', $subVal))
  308. ) {
  309. return TRUE;
  310. }
  311. }
  312. return FALSE;
  313. }
  314. return TRUE;
  315. }
  316. // No date...
  317. return FALSE;
  318. } // function isDateTimeFormatCode()
  319. /**
  320. * Convert a date/time string to Excel time
  321. *
  322. * @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10'
  323. * @return float|FALSE Excel date/time serial value
  324. */
  325. public static function stringToExcel($dateValue = '')
  326. {
  327. if (strlen($dateValue) < 2)
  328. return FALSE;
  329. if (!preg_match('/^(\d{1,4}[ \.\/\-][A-Z]{3,9}([ \.\/\-]\d{1,4})?|[A-Z]{3,9}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?|\d{1,4}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?)( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/iu', $dateValue))
  330. return FALSE;
  331. $dateValueNew = PHPExcel_Calculation_DateTime::DATEVALUE($dateValue);
  332. if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) {
  333. return FALSE;
  334. } else {
  335. if (strpos($dateValue, ':') !== FALSE) {
  336. $timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($dateValue);
  337. if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) {
  338. return FALSE;
  339. }
  340. $dateValueNew += $timeValue;
  341. }
  342. return $dateValueNew;
  343. }
  344. }
  345. public static function monthStringToNumber($month)
  346. {
  347. $monthIndex = 1;
  348. foreach (self::$_monthNames as $shortMonthName => $longMonthName) {
  349. if (($month === $longMonthName) || ($month === $shortMonthName)) {
  350. return $monthIndex;
  351. }
  352. ++$monthIndex;
  353. }
  354. return $month;
  355. }
  356. public static function dayStringToNumber($day)
  357. {
  358. $strippedDayValue = (str_replace(self::$_numberSuffixes, '', $day));
  359. if (is_numeric($strippedDayValue)) {
  360. return $strippedDayValue;
  361. }
  362. return $day;
  363. }
  364. }