You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

432 rivejä
14 KiB

  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  6. var _momentTimezone = require('moment-timezone');
  7. var _momentTimezone2 = _interopRequireDefault(_momentTimezone);
  8. var _func = require('./func');
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10. // loads moment-timezone's timezone data, which comes from the
  11. // IANA Time Zone Database at https://www.iana.org/time-zones
  12. _momentTimezone2.default.tz.load({
  13. zones: [],
  14. links: [],
  15. version: 'latest'
  16. });
  17. var guessUserTz = function guessUserTz() {
  18. // User-Agent sniffing is not always reliable, but is the recommended technique
  19. // for determining whether or not we're on a mobile device according to MDN
  20. // see https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#Mobile_Tablet_or_Desktop
  21. var isMobile = global.navigator !== undefined ? global.navigator.userAgent.match(/Mobi/) : false;
  22. var supportsIntl = global.Intl !== undefined;
  23. var userTz = void 0;
  24. if (isMobile && supportsIntl) {
  25. // moment-timezone gives preference to the Intl API regardless of device type,
  26. // so unset global.Intl to trick moment-timezone into using its fallback
  27. // see https://github.com/moment/moment-timezone/issues/441
  28. // TODO: Clean this up when that issue is resolved
  29. var globalIntl = global.Intl;
  30. global.Intl = undefined;
  31. userTz = _momentTimezone2.default.tz.guess();
  32. global.Intl = globalIntl;
  33. } else {
  34. userTz = _momentTimezone2.default.tz.guess();
  35. }
  36. // return GMT if we're unable to guess or the system is using UTC
  37. if (!userTz || userTz === 'UTC') return getTzForName('Etc/Greenwich');
  38. try {
  39. return getTzForName(userTz);
  40. } catch (e) {
  41. console.error(e);
  42. return getTzForName('Etc/Greenwich');
  43. }
  44. };
  45. /**
  46. * Create a time data object using moment.
  47. * If a time is provided, just format it; if not, use the current time.
  48. *
  49. * @function getValidTimeData
  50. * @param {string} time a time; defaults to now
  51. * @param {string} meridiem AM or PM; defaults to AM via moment
  52. * @param {Number} timeMode 12 or 24-hour mode
  53. * @param {string} tz a timezone name; defaults to guessing a user's tz or GMT
  54. * @return {Object} a key-value representation of time data
  55. */
  56. var getValidTimeData = function getValidTimeData() {
  57. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  58. var tz = options.tz,
  59. time = options.time,
  60. timeMode = options.timeMode,
  61. _options$useTz = options.useTz,
  62. useTz = _options$useTz === undefined ? true : _options$useTz,
  63. _options$meridiem = options.meridiem,
  64. meridiem = _options$meridiem === undefined ? null : _options$meridiem;
  65. var validMeridiem = getValidMeridiem(meridiem);
  66. // when we only have a valid meridiem, that implies a 12h mode
  67. var mode = validMeridiem && !timeMode ? 12 : timeMode || 24;
  68. var timezone = tz || guessUserTz().zoneName;
  69. var validMode = getValidateTimeMode(mode);
  70. var validTime = getValidTimeString(time, validMeridiem);
  71. var format12 = 'hh:mmA';
  72. var format24 = 'HH:mmA';
  73. // What format is the hour we provide to moment below in?
  74. var hourFormat = validMode === 12 ? format12 : format24;
  75. var time24 = void 0;
  76. var time12 = void 0;
  77. var formatTime = (0, _momentTimezone2.default)('1970-01-01 ' + validTime, 'YYYY-MM-DD ' + hourFormat, 'en');
  78. if (time || !useTz) {
  79. time24 = (validTime ? formatTime.format(format24) : (0, _momentTimezone2.default)().format(format24)).split(/:/);
  80. time12 = (validTime ? formatTime.format(format12) : (0, _momentTimezone2.default)().format(format12)).split(/:/);
  81. } else {
  82. time24 = (validTime ? formatTime.tz(timezone).format(format24) : (0, _momentTimezone2.default)().tz(timezone).format(format24)).split(/:/);
  83. time12 = (validTime ? formatTime.tz(timezone).format(format12) : (0, _momentTimezone2.default)().tz(timezone).format(format12)).split(/:/);
  84. }
  85. var timeData = {
  86. timezone: timezone,
  87. mode: validMode,
  88. hour24: (0, _func.head)(time24),
  89. minute: (0, _func.last)(time24).slice(0, 2),
  90. hour12: (0, _func.head)(time12).replace(/^0/, ''),
  91. meridiem: validMode === 12 ? (0, _func.last)(time12).slice(2) : null
  92. };
  93. return timeData;
  94. };
  95. /**
  96. * Format the current time as a string
  97. * @function getCurrentTime
  98. * @return {string}
  99. */
  100. var getCurrentTime = function getCurrentTime() {
  101. var time = getValidTimeData();
  102. return time.hour24 + ':' + time.minute;
  103. };
  104. /**
  105. * Get an integer representation of a time.
  106. * @function getValidateIntTime
  107. * @param {string} time
  108. * @return {Number}
  109. */
  110. var getValidateIntTime = function getValidateIntTime(time) {
  111. if (isNaN(parseInt(time, 10))) {
  112. return 0;
  113. }
  114. return parseInt(time, 10);
  115. };
  116. /**
  117. * Validate, set a default for, and stringify time data.
  118. * @function getValidateTime
  119. * @param {string}
  120. * @return {string}
  121. */
  122. var getValidateTime = function getValidateTime(time) {
  123. var result = time;
  124. if (_func.is.undefined(result)) {
  125. result = '00';
  126. }
  127. if (isNaN(parseInt(result, 10))) {
  128. result = '00';
  129. }
  130. if (parseInt(result, 10) < 10) {
  131. result = '0' + parseInt(result, 10);
  132. }
  133. return '' + result;
  134. };
  135. /**
  136. * Given a time and meridiem, produce a time string to pass to moment
  137. * @function getValidTimeString
  138. * @param {string} time
  139. * @param {string} meridiem
  140. * @return {string}
  141. */
  142. var getValidTimeString = function getValidTimeString(time, meridiem) {
  143. if (_func.is.string(time)) {
  144. var validTime = time && time.indexOf(':').length >= 0 ? time.split(/:/).map(function (t) {
  145. return getValidateTime(t);
  146. }).join(':') : time;
  147. var hourAsInt = parseInt((0, _func.head)(validTime.split(/:/)), 10);
  148. var is12hTime = hourAsInt > 0 && hourAsInt <= 12;
  149. validTime = validTime && meridiem && is12hTime ? validTime + ' ' + meridiem : validTime;
  150. return validTime;
  151. }
  152. return time;
  153. };
  154. /**
  155. * Given a meridiem, try to ensure that it's formatted for use with moment
  156. * @function getValidMeridiem
  157. * @param {string} meridiem
  158. * @return {string}
  159. */
  160. var getValidMeridiem = function getValidMeridiem(meridiem) {
  161. if (_func.is.string(meridiem)) {
  162. return meridiem && meridiem.match(/am|pm/i) ? meridiem.toLowerCase() : null;
  163. }
  164. return meridiem;
  165. };
  166. /**
  167. * Ensure that a meridiem passed as a prop has a valid value
  168. * @function getValidateMeridiem
  169. * @param {string} time
  170. * @param {string|Number} timeMode
  171. * @return {string|null}
  172. */
  173. var getValidateMeridiem = function getValidateMeridiem(time, timeMode) {
  174. var validateTime = time || getCurrentTime();
  175. var mode = parseInt(timeMode, 10);
  176. // eslint-disable-next-line no-unused-vars
  177. var hour = validateTime.split(/:/)[0];
  178. hour = getValidateIntTime(hour);
  179. if (mode === 12) return hour > 12 ? 'PM' : 'AM';
  180. return null;
  181. };
  182. /**
  183. * Validate and set a sensible default for time modes.
  184. *
  185. * @function getValidateTimeMode
  186. * @param {string|Number} timeMode
  187. * @return {Number}
  188. */
  189. var getValidateTimeMode = function getValidateTimeMode(timeMode) {
  190. var mode = parseInt(timeMode, 10);
  191. if (isNaN(mode)) {
  192. return 24;
  193. }
  194. if (mode !== 24 && mode !== 12) {
  195. return 24;
  196. }
  197. return mode;
  198. };
  199. var tzNames = function () {
  200. // We want to subset the existing timezone data as much as possible, both for efficiency
  201. // and to avoid confusing the user. Here, we focus on removing reduntant timezone names
  202. // and timezone names for timezones we don't necessarily care about, like Antarctica, and
  203. // special timezone names that exist for convenience.
  204. var scrubbedPrefixes = ['Antarctica', 'Arctic', 'Chile'];
  205. var scrubbedSuffixes = ['ACT', 'East', 'Knox_IN', 'LHI', 'North', 'NSW', 'South', 'West'];
  206. var tznames = _momentTimezone2.default.tz.names().filter(function (name) {
  207. return name.indexOf('/') >= 0;
  208. }).filter(function (name) {
  209. return !scrubbedPrefixes.indexOf(name.split('/')[0]) >= 0;
  210. }).filter(function (name) {
  211. return !scrubbedSuffixes.indexOf(name.split('/').slice(-1)[0]) >= 0;
  212. });
  213. return tznames;
  214. }();
  215. // We need a human-friendly city name for each timezone identifier
  216. // counting Canada/*, Mexico/*, and US/* allows users to search for
  217. // things like 'Eastern' or 'Mountain' and get matches back
  218. var tzCities = tzNames.map(function (name) {
  219. return ['Canada', 'Mexico', 'US'].indexOf(name.split('/')[0]) >= 0 ? name : name.split('/').slice(-1)[0];
  220. }).map(function (name) {
  221. return name.replace(/_/g, ' ');
  222. });
  223. // Provide a mapping between a human-friendly city name and its corresponding
  224. // timezone identifier and timezone abbreviation as a named export.
  225. // We can fuzzy match on any of these.
  226. var tzMaps = tzCities.map(function (city) {
  227. var tzMap = {};
  228. var tzName = tzNames[tzCities.indexOf(city)];
  229. tzMap.city = city;
  230. tzMap.zoneName = tzName;
  231. tzMap.zoneAbbr = (0, _momentTimezone2.default)().tz(tzName).zoneAbbr();
  232. return tzMap;
  233. });
  234. var getTzForCity = function getTzForCity(city) {
  235. var val = city.toLowerCase();
  236. var maps = tzMaps.filter(function (tzMap) {
  237. return tzMap.city.toLowerCase() === val;
  238. });
  239. return (0, _func.head)(maps);
  240. };
  241. var getTzCountryAndCity = function getTzCountryAndCity(name) {
  242. var sections = name.split('/');
  243. return {
  244. country: sections[0].toLowerCase(),
  245. city: sections.slice(-1)[0].toLowerCase()
  246. };
  247. };
  248. var _matchTzByName = function _matchTzByName(target, name) {
  249. var v1 = getTzCountryAndCity(target);
  250. var v2 = getTzCountryAndCity(name);
  251. return v1.country === v2.country && v1.city === v2.city;
  252. };
  253. var getTzForName = function getTzForName(name) {
  254. var maps = tzMaps.filter(function (tzMap) {
  255. return tzMap.zoneName === name;
  256. });
  257. if (!maps.length && /\//.test(name)) {
  258. maps = tzMaps.filter(function (tzMap) {
  259. return tzMap.zoneAbbr === name;
  260. });
  261. }
  262. if (!maps.length) {
  263. maps = tzMaps.filter(function (tzMap) {
  264. return _matchTzByName(tzMap.zoneName, name);
  265. });
  266. }
  267. if (!maps.length) {
  268. throw new Error('Can not find target timezone for ' + name);
  269. }
  270. return (0, _func.head)(maps);
  271. };
  272. var hourFormatter = function hourFormatter(hour) {
  273. var defaultTime = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '00:00';
  274. if (!hour) return defaultTime;
  275. var _$split = ('' + hour).split(/[:|\s]/),
  276. _$split2 = _slicedToArray(_$split, 3),
  277. h = _$split2[0],
  278. m = _$split2[1],
  279. meridiem = _$split2[2];
  280. if (meridiem && meridiem.toLowerCase() === 'pm') meridiem = 'PM';
  281. if (meridiem && meridiem.toLowerCase() === 'am') meridiem = 'AM';
  282. if (meridiem && meridiem !== 'AM' && meridiem !== 'PM') meridiem = 'AM';
  283. if (!h || isNaN(h)) h = '0';
  284. if (!meridiem && Number(h > 24)) h = Number(h) - 24;
  285. if (meridiem && Number(h > 12)) h = Number(h) - 12;
  286. if (!m || isNaN(m) || Number(m) >= 60) m = '0';
  287. if (Number(h) < 10) h = '0' + Number(h);
  288. if (Number(m) < 10) m = '0' + Number(m);
  289. return meridiem ? h + ':' + m + ' ' + meridiem : h + ':' + m;
  290. };
  291. var withoutMeridiem = function withoutMeridiem(hour) {
  292. return hour.replace(/\s[P|A]M$/, '');
  293. };
  294. var getStartAndEnd = function getStartAndEnd(from, to) {
  295. var current = (0, _momentTimezone2.default)();
  296. var date = current.format('YYYY-MM-DD');
  297. var nextDate = current.add(1, 'day').format('YYYY-MM-DD');
  298. var f = hourFormatter(from, '00:00');
  299. var t = hourFormatter(to, '23:30');
  300. var start = date + ' ' + withoutMeridiem(f);
  301. var endTmp = withoutMeridiem(t);
  302. var end = (0, _momentTimezone2.default)(date + ' ' + endTmp) <= (0, _momentTimezone2.default)(start) ? nextDate + ' ' + endTmp : date + ' ' + endTmp;
  303. if (/PM$/.test(f)) start = (0, _momentTimezone2.default)(start).add(12, 'hours').format('YYYY-MM-DD HH:mm');
  304. if (/PM$/.test(t)) end = (0, _momentTimezone2.default)(end).add(12, 'hours').format('YYYY-MM-DD HH:mm');
  305. return {
  306. start: start,
  307. end: end
  308. };
  309. };
  310. var get12ModeTimes = function get12ModeTimes(_ref) {
  311. var from = _ref.from,
  312. to = _ref.to,
  313. _ref$step = _ref.step,
  314. step = _ref$step === undefined ? 30 : _ref$step,
  315. _ref$unit = _ref.unit,
  316. unit = _ref$unit === undefined ? 'minutes' : _ref$unit;
  317. var _getStartAndEnd = getStartAndEnd(from, to),
  318. start = _getStartAndEnd.start,
  319. end = _getStartAndEnd.end;
  320. var times = [];
  321. var time = (0, _momentTimezone2.default)(start);
  322. while (time <= (0, _momentTimezone2.default)(end)) {
  323. var hour = Number(time.format('HH'));
  324. times.push(time.format('hh:mm') + ' ' + (hour >= 12 ? 'PM' : 'AM'));
  325. time = time.add(step, unit);
  326. }
  327. return times;
  328. };
  329. var get24ModeTimes = function get24ModeTimes(_ref2) {
  330. var from = _ref2.from,
  331. to = _ref2.to,
  332. _ref2$step = _ref2.step,
  333. step = _ref2$step === undefined ? 30 : _ref2$step,
  334. _ref2$unit = _ref2.unit,
  335. unit = _ref2$unit === undefined ? 'minutes' : _ref2$unit;
  336. var _getStartAndEnd2 = getStartAndEnd(from, to),
  337. start = _getStartAndEnd2.start,
  338. end = _getStartAndEnd2.end;
  339. var times = [];
  340. var time = (0, _momentTimezone2.default)(start);
  341. while (time <= (0, _momentTimezone2.default)(end)) {
  342. times.push(time.format('HH:mm'));
  343. time = time.add(step, unit);
  344. }
  345. return times;
  346. };
  347. exports.default = {
  348. tzMaps: tzMaps,
  349. guessUserTz: guessUserTz,
  350. hourFormatter: hourFormatter,
  351. getStartAndEnd: getStartAndEnd,
  352. get12ModeTimes: get12ModeTimes,
  353. get24ModeTimes: get24ModeTimes,
  354. withoutMeridiem: withoutMeridiem,
  355. time: getValidTimeData,
  356. current: getCurrentTime,
  357. tzForCity: getTzForCity,
  358. tzForName: getTzForName,
  359. validate: getValidateTime,
  360. validateInt: getValidateIntTime,
  361. validateMeridiem: getValidateMeridiem,
  362. validateTimeMode: getValidateTimeMode
  363. };