DateTools.hx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. /**
  23. The DateTools class contains some extra functionalities for handling `Date`
  24. instances and timestamps.
  25. In the context of Haxe dates, a timestamp is defined as the number of
  26. milliseconds elapsed since 1st January 1970.
  27. **/
  28. class DateTools {
  29. #if php
  30. #elseif (neko && !(macro || interp))
  31. static var date_format = neko.Lib.load("std", "date_format", 2);
  32. #else
  33. static var DAY_SHORT_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  34. static var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  35. static var MONTH_SHORT_NAMES = [
  36. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  37. ];
  38. static var MONTH_NAMES = [
  39. "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
  40. ];
  41. private static function __format_get(d:Date, e:String):String {
  42. return switch (e) {
  43. case "%":
  44. "%";
  45. case "a":
  46. DAY_SHORT_NAMES[d.getDay()];
  47. case "A":
  48. DAY_NAMES[d.getDay()];
  49. case "b", "h":
  50. MONTH_SHORT_NAMES[d.getMonth()];
  51. case "B":
  52. MONTH_NAMES[d.getMonth()];
  53. case "C":
  54. untyped StringTools.lpad(Std.string(Std.int(d.getFullYear() / 100)), "0", 2);
  55. case "d":
  56. untyped StringTools.lpad(Std.string(d.getDate()), "0", 2);
  57. case "D":
  58. __format(d, "%m/%d/%y");
  59. case "e":
  60. untyped Std.string(d.getDate());
  61. case "F":
  62. __format(d, "%Y-%m-%d");
  63. case "H", "k":
  64. untyped StringTools.lpad(Std.string(d.getHours()), if (e == "H") "0" else " ", 2);
  65. case "I", "l":
  66. var hour = d.getHours() % 12;
  67. untyped StringTools.lpad(Std.string(hour == 0 ? 12 : hour), if (e == "I") "0" else " ", 2);
  68. case "m":
  69. untyped StringTools.lpad(Std.string(d.getMonth() + 1), "0", 2);
  70. case "M":
  71. untyped StringTools.lpad(Std.string(d.getMinutes()), "0", 2);
  72. case "n":
  73. "\n";
  74. case "p":
  75. untyped if (d.getHours() > 11) "PM"; else "AM";
  76. case "r":
  77. __format(d, "%I:%M:%S %p");
  78. case "R":
  79. __format(d, "%H:%M");
  80. case "s":
  81. Std.string(Std.int(d.getTime() / 1000));
  82. case "S":
  83. untyped StringTools.lpad(Std.string(d.getSeconds()), "0", 2);
  84. case "t":
  85. "\t";
  86. case "T":
  87. __format(d, "%H:%M:%S");
  88. case "u":
  89. untyped {
  90. var t = d.getDay();
  91. if (t == 0)
  92. "7";
  93. else
  94. Std.string(t);
  95. }
  96. case "w":
  97. untyped Std.string(d.getDay());
  98. case "y":
  99. untyped StringTools.lpad(Std.string(d.getFullYear() % 100), "0", 2);
  100. case "Y":
  101. untyped Std.string(d.getFullYear());
  102. default:
  103. throw "Date.format %" + e + "- not implemented yet.";
  104. }
  105. }
  106. private static function __format(d:Date, f:String):String {
  107. var r = new StringBuf();
  108. var p = 0;
  109. while (true) {
  110. var np = f.indexOf("%", p);
  111. if (np < 0)
  112. break;
  113. r.addSub(f, p, np - p);
  114. r.add(__format_get(d, f.substr(np + 1, 1)));
  115. p = np + 2;
  116. }
  117. r.addSub(f, p, f.length - p);
  118. return r.toString();
  119. }
  120. #end
  121. /**
  122. Format the date `d` according to the format `f`. The format is
  123. compatible with the `strftime` standard format, except that there is no
  124. support in Flash and JS for day and months names (due to lack of proper
  125. internationalization API). On Haxe/Neko/Windows, some formats are not
  126. supported.
  127. ```haxe
  128. var t = DateTools.format(Date.now(), "%Y-%m-%d_%H:%M:%S");
  129. // 2016-07-08_14:44:05
  130. var t = DateTools.format(Date.now(), "%r");
  131. // 02:44:05 PM
  132. var t = DateTools.format(Date.now(), "%T");
  133. // 14:44:05
  134. var t = DateTools.format(Date.now(), "%F");
  135. // 2016-07-08
  136. ```
  137. **/
  138. public static function format(d:Date, f:String):String {
  139. #if (neko && !(macro || interp))
  140. return new String(untyped date_format(d.__t, f.__s));
  141. #elseif php
  142. return php.Global.strftime(f, php.Syntax.int(@:privateAccess d.__t));
  143. #else
  144. return __format(d, f);
  145. #end
  146. }
  147. /**
  148. Returns the result of adding timestamp `t` to Date `d`.
  149. This is a convenience function for calling
  150. `Date.fromTime(d.getTime() + t)`.
  151. **/
  152. public static inline function delta(d:Date, t:Float):Date {
  153. return Date.fromTime(d.getTime() + t);
  154. }
  155. static var DAYS_OF_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  156. /**
  157. Returns the number of days in the month of Date `d`.
  158. This method handles leap years.
  159. **/
  160. public static function getMonthDays(d:Date):Int {
  161. var month = d.getMonth();
  162. var year = d.getFullYear();
  163. if (month != 1)
  164. return DAYS_OF_MONTH[month];
  165. var isB = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
  166. return if (isB) 29 else 28;
  167. }
  168. /**
  169. Converts a number of seconds to a timestamp.
  170. **/
  171. public static inline function seconds(n:Float):Float {
  172. return n * 1000.0;
  173. }
  174. /**
  175. Converts a number of minutes to a timestamp.
  176. **/
  177. public static inline function minutes(n:Float):Float {
  178. return n * 60.0 * 1000.0;
  179. }
  180. /**
  181. Converts a number of hours to a timestamp.
  182. **/
  183. public static inline function hours(n:Float):Float {
  184. return n * 60.0 * 60.0 * 1000.0;
  185. }
  186. /**
  187. Converts a number of days to a timestamp.
  188. **/
  189. public static inline function days(n:Float):Float {
  190. return n * 24.0 * 60.0 * 60.0 * 1000.0;
  191. }
  192. /**
  193. Separate a date-time into several components
  194. **/
  195. public static function parse(t:Float) {
  196. var s = t / 1000;
  197. var m = s / 60;
  198. var h = m / 60;
  199. return {
  200. ms: t % 1000,
  201. seconds: Std.int(s % 60),
  202. minutes: Std.int(m % 60),
  203. hours: Std.int(h % 24),
  204. days: Std.int(h / 24),
  205. };
  206. }
  207. /**
  208. Build a date-time from several components
  209. **/
  210. public static function make(o:{
  211. ms:Float,
  212. seconds:Int,
  213. minutes:Int,
  214. hours:Int,
  215. days:Int
  216. }) {
  217. return o.ms + 1000.0 * (o.seconds + 60.0 * (o.minutes + 60.0 * (o.hours + 24.0 * o.days)));
  218. }
  219. #if (js || flash || php || cpp || python)
  220. /**
  221. Retrieve Unix timestamp value from Date components. Takes same argument sequence as the Date constructor.
  222. **/
  223. public static #if (js || flash || php) inline #end function makeUtc(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Float {
  224. #if (js || flash || python)
  225. return untyped Date.UTC(year, month, day, hour, min, sec);
  226. #elseif php
  227. return php.Global.gmmktime(hour, min, sec, month + 1, day, year) * 1000;
  228. #elseif cpp
  229. return untyped __global__.__hxcpp_utc_date(year, month, day, hour, min, sec) * 1000.0;
  230. #else
  231. // TODO
  232. return 0.;
  233. #end
  234. }
  235. #end
  236. }