a zip code crypto-currency system good for red ONLY

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import { isBlank, isPresent, isString } from './util';
  2. export function renderDateTime(template, value, locale) {
  3. if (isBlank(value)) {
  4. return '';
  5. }
  6. let tokens = [];
  7. let hasText = false;
  8. FORMAT_KEYS.forEach((format, index) => {
  9. if (template.indexOf(format.f) > -1) {
  10. const token = '{' + index + '}';
  11. const text = renderTextFormat(format.f, value[format.k], value, locale);
  12. if (!hasText && text && isPresent(value[format.k])) {
  13. hasText = true;
  14. }
  15. tokens.push(token, text);
  16. template = template.replace(format.f, token);
  17. }
  18. });
  19. if (!hasText) {
  20. return '';
  21. }
  22. for (let i = 0; i < tokens.length; i += 2) {
  23. template = template.replace(tokens[i], tokens[i + 1]);
  24. }
  25. return template;
  26. }
  27. export function renderTextFormat(format, value, date, locale) {
  28. if (format === FORMAT_DDDD || format === FORMAT_DDD) {
  29. try {
  30. value = (new Date(date.year, date.month - 1, date.day)).getDay();
  31. if (format === FORMAT_DDDD) {
  32. return (isPresent(locale.dayNames) ? locale.dayNames : DAY_NAMES)[value];
  33. }
  34. return (isPresent(locale.dayShortNames) ? locale.dayShortNames : DAY_SHORT_NAMES)[value];
  35. }
  36. catch (e) { }
  37. return '';
  38. }
  39. if (format === FORMAT_A) {
  40. return date ? date.hour < 12 ? 'AM' : 'PM' : isPresent(value) ? value.toUpperCase() : '';
  41. }
  42. if (format === FORMAT_a) {
  43. return date ? date.hour < 12 ? 'am' : 'pm' : isPresent(value) ? value : '';
  44. }
  45. if (isBlank(value)) {
  46. return '';
  47. }
  48. if (format === FORMAT_YY || format === FORMAT_MM ||
  49. format === FORMAT_DD || format === FORMAT_HH ||
  50. format === FORMAT_mm || format === FORMAT_ss) {
  51. return twoDigit(value);
  52. }
  53. if (format === FORMAT_YYYY) {
  54. return fourDigit(value);
  55. }
  56. if (format === FORMAT_MMMM) {
  57. return (isPresent(locale.monthNames) ? locale.monthNames : MONTH_NAMES)[value - 1];
  58. }
  59. if (format === FORMAT_MMM) {
  60. return (isPresent(locale.monthShortNames) ? locale.monthShortNames : MONTH_SHORT_NAMES)[value - 1];
  61. }
  62. if (format === FORMAT_hh || format === FORMAT_h) {
  63. if (value === 0) {
  64. return '12';
  65. }
  66. if (value > 12) {
  67. value -= 12;
  68. }
  69. if (format === FORMAT_hh && value < 10) {
  70. return ('0' + value);
  71. }
  72. }
  73. return value.toString();
  74. }
  75. export function dateValueRange(format, min, max) {
  76. let opts = [];
  77. let i;
  78. if (format === FORMAT_YYYY || format === FORMAT_YY) {
  79. // year
  80. i = max.year;
  81. while (i >= min.year) {
  82. opts.push(i--);
  83. }
  84. }
  85. else if (format === FORMAT_MMMM || format === FORMAT_MMM ||
  86. format === FORMAT_MM || format === FORMAT_M ||
  87. format === FORMAT_hh || format === FORMAT_h) {
  88. // month or 12-hour
  89. for (i = 1; i < 13; i++) {
  90. opts.push(i);
  91. }
  92. }
  93. else if (format === FORMAT_DDDD || format === FORMAT_DDD ||
  94. format === FORMAT_DD || format === FORMAT_D) {
  95. // day
  96. for (i = 1; i < 32; i++) {
  97. opts.push(i);
  98. }
  99. }
  100. else if (format === FORMAT_HH || format === FORMAT_H) {
  101. // 24-hour
  102. for (i = 0; i < 24; i++) {
  103. opts.push(i);
  104. }
  105. }
  106. else if (format === FORMAT_mm || format === FORMAT_m) {
  107. // minutes
  108. for (i = 0; i < 60; i++) {
  109. opts.push(i);
  110. }
  111. }
  112. else if (format === FORMAT_ss || format === FORMAT_s) {
  113. // seconds
  114. for (i = 0; i < 60; i++) {
  115. opts.push(i);
  116. }
  117. }
  118. else if (format === FORMAT_A || format === FORMAT_a) {
  119. // AM/PM
  120. opts.push('am', 'pm');
  121. }
  122. return opts;
  123. }
  124. export function dateSortValue(year, month, day, hour = 0, minute = 0) {
  125. return parseInt(`1${fourDigit(year)}${twoDigit(month)}${twoDigit(day)}${twoDigit(hour)}${twoDigit(minute)}`, 10);
  126. }
  127. export function dateDataSortValue(data) {
  128. if (data) {
  129. return dateSortValue(data.year, data.month, data.day, data.hour, data.minute);
  130. }
  131. return -1;
  132. }
  133. export function daysInMonth(month, year) {
  134. return (month === 4 || month === 6 || month === 9 || month === 11) ? 30 : (month === 2) ? isLeapYear(year) ? 29 : 28 : 31;
  135. }
  136. export function isLeapYear(year) {
  137. return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
  138. }
  139. const ISO_8601_REGEXP = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/;
  140. const TIME_REGEXP = /^((\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/;
  141. export function parseDate(val) {
  142. // manually parse IS0 cuz Date.parse cannot be trusted
  143. // ISO 8601 format: 1994-12-15T13:47:20Z
  144. let parse;
  145. if (isPresent(val) && val !== '') {
  146. // try parsing for just time first, HH:MM
  147. parse = TIME_REGEXP.exec(val);
  148. if (isPresent(parse)) {
  149. // adjust the array so it fits nicely with the datetime parse
  150. parse.unshift(undefined, undefined);
  151. parse[2] = parse[3] = undefined;
  152. }
  153. else {
  154. // try parsing for full ISO datetime
  155. parse = ISO_8601_REGEXP.exec(val);
  156. }
  157. }
  158. if (isBlank(parse)) {
  159. // wasn't able to parse the ISO datetime
  160. return null;
  161. }
  162. // ensure all the parse values exist with at least 0
  163. for (let i = 1; i < 8; i++) {
  164. parse[i] = (parse[i] !== undefined ? parseInt(parse[i], 10) : null);
  165. }
  166. let tzOffset = 0;
  167. if (isPresent(parse[9]) && isPresent(parse[10])) {
  168. // hours
  169. tzOffset = parseInt(parse[10], 10) * 60;
  170. if (isPresent(parse[11])) {
  171. // minutes
  172. tzOffset += parseInt(parse[11], 10);
  173. }
  174. if (parse[9] === '-') {
  175. // + or -
  176. tzOffset *= -1;
  177. }
  178. }
  179. return {
  180. year: parse[1],
  181. month: parse[2],
  182. day: parse[3],
  183. hour: parse[4],
  184. minute: parse[5],
  185. second: parse[6],
  186. millisecond: parse[7],
  187. tzOffset: tzOffset,
  188. };
  189. }
  190. export function compareDates(d1, d2) {
  191. const date1 = new Date(d1.year, d1.month, d1.day, d1.hour, d1.minute, d1.second);
  192. const date2 = new Date(d2.year, d2.month, d2.day, d2.hour, d2.minute, d2.second);
  193. return date1.getTime() - date2.getTime();
  194. }
  195. export function updateDate(existingData, newData) {
  196. if (isPresent(newData) && newData !== '') {
  197. if (isString(newData)) {
  198. // new date is a string, and hopefully in the ISO format
  199. // convert it to our DateTimeData if a valid ISO
  200. newData = parseDate(newData);
  201. if (newData) {
  202. // successfully parsed the ISO string to our DateTimeData
  203. Object.assign(existingData, newData);
  204. return true;
  205. }
  206. }
  207. else if ((isPresent(newData.year) || isPresent(newData.hour) || isPresent(newData.month) || isPresent(newData.day) || isPresent(newData.minute) || isPresent(newData.second))) {
  208. // newData is from of a datetime picker's selected values
  209. // update the existing DateTimeData data with the new values
  210. // do some magic for 12-hour values
  211. if (isPresent(newData.ampm) && isPresent(newData.hour)) {
  212. if (newData.ampm.value === 'pm') {
  213. newData.hour.value = (newData.hour.value === 12 ? 12 : newData.hour.value + 12);
  214. }
  215. else {
  216. newData.hour.value = (newData.hour.value === 12 ? 0 : newData.hour.value);
  217. }
  218. }
  219. // merge new values from the picker's selection
  220. // to the existing DateTimeData values
  221. for (const k in newData) {
  222. existingData[k] = newData[k].value;
  223. }
  224. return true;
  225. }
  226. // eww, invalid data
  227. console.warn(`Error parsing date: "${newData}". Please provide a valid ISO 8601 datetime format: https://www.w3.org/TR/NOTE-datetime`);
  228. }
  229. else {
  230. // blank data, clear everything out
  231. for (const k in existingData) {
  232. delete existingData[k];
  233. }
  234. }
  235. return false;
  236. }
  237. export function parseTemplate(template) {
  238. const formats = [];
  239. template = template.replace(/[^\w\s]/gi, ' ');
  240. FORMAT_KEYS.forEach(format => {
  241. if (format.f.length > 1 && template.indexOf(format.f) > -1 && template.indexOf(format.f + format.f.charAt(0)) < 0) {
  242. template = template.replace(format.f, ' ' + format.f + ' ');
  243. }
  244. });
  245. const words = template.split(' ').filter(w => w.length > 0);
  246. words.forEach((word, i) => {
  247. FORMAT_KEYS.forEach(format => {
  248. if (word === format.f) {
  249. if (word === FORMAT_A || word === FORMAT_a) {
  250. // this format is an am/pm format, so it's an "a" or "A"
  251. if ((formats.indexOf(FORMAT_h) < 0 && formats.indexOf(FORMAT_hh) < 0) ||
  252. VALID_AMPM_PREFIX.indexOf(words[i - 1]) === -1) {
  253. // template does not already have a 12-hour format
  254. // or this am/pm format doesn't have a hour, minute, or second format immediately before it
  255. // so do not treat this word "a" or "A" as the am/pm format
  256. return;
  257. }
  258. }
  259. formats.push(word);
  260. }
  261. });
  262. });
  263. return formats;
  264. }
  265. export function getValueFromFormat(date, format) {
  266. if (format === FORMAT_A || format === FORMAT_a) {
  267. return (date.hour < 12 ? 'am' : 'pm');
  268. }
  269. if (format === FORMAT_hh || format === FORMAT_h) {
  270. return (date.hour > 12 ? date.hour - 12 : date.hour);
  271. }
  272. return date[convertFormatToKey(format)];
  273. }
  274. export function convertFormatToKey(format) {
  275. for (const k in FORMAT_KEYS) {
  276. if (FORMAT_KEYS[k].f === format) {
  277. return FORMAT_KEYS[k].k;
  278. }
  279. }
  280. return null;
  281. }
  282. export function convertDataToISO(data) {
  283. // https://www.w3.org/TR/NOTE-datetime
  284. let rtn = '';
  285. if (isPresent(data)) {
  286. if (isPresent(data.year)) {
  287. // YYYY
  288. rtn = fourDigit(data.year);
  289. if (isPresent(data.month)) {
  290. // YYYY-MM
  291. rtn += '-' + twoDigit(data.month);
  292. if (isPresent(data.day)) {
  293. // YYYY-MM-DD
  294. rtn += '-' + twoDigit(data.day);
  295. if (isPresent(data.hour)) {
  296. // YYYY-MM-DDTHH:mm:SS
  297. rtn += `T${twoDigit(data.hour)}:${twoDigit(data.minute)}:${twoDigit(data.second)}`;
  298. if (data.millisecond > 0) {
  299. // YYYY-MM-DDTHH:mm:SS.SSS
  300. rtn += '.' + threeDigit(data.millisecond);
  301. }
  302. if (isBlank(data.tzOffset) || data.tzOffset === 0) {
  303. // YYYY-MM-DDTHH:mm:SSZ
  304. rtn += 'Z';
  305. }
  306. else {
  307. // YYYY-MM-DDTHH:mm:SS+/-HH:mm
  308. rtn += (data.tzOffset > 0 ? '+' : '-') + twoDigit(Math.floor(data.tzOffset / 60)) + ':' + twoDigit(data.tzOffset % 60);
  309. }
  310. }
  311. }
  312. }
  313. }
  314. else if (isPresent(data.hour)) {
  315. // HH:mm
  316. rtn = twoDigit(data.hour) + ':' + twoDigit(data.minute);
  317. if (isPresent(data.second)) {
  318. // HH:mm:SS
  319. rtn += ':' + twoDigit(data.second);
  320. if (isPresent(data.millisecond)) {
  321. // HH:mm:SS.SSS
  322. rtn += '.' + threeDigit(data.millisecond);
  323. }
  324. }
  325. }
  326. }
  327. return rtn;
  328. }
  329. function twoDigit(val) {
  330. return ('0' + (isPresent(val) ? Math.abs(val) : '0')).slice(-2);
  331. }
  332. function threeDigit(val) {
  333. return ('00' + (isPresent(val) ? Math.abs(val) : '0')).slice(-3);
  334. }
  335. function fourDigit(val) {
  336. return ('000' + (isPresent(val) ? Math.abs(val) : '0')).slice(-4);
  337. }
  338. const FORMAT_YYYY = 'YYYY';
  339. const FORMAT_YY = 'YY';
  340. const FORMAT_MMMM = 'MMMM';
  341. const FORMAT_MMM = 'MMM';
  342. const FORMAT_MM = 'MM';
  343. const FORMAT_M = 'M';
  344. const FORMAT_DDDD = 'DDDD';
  345. const FORMAT_DDD = 'DDD';
  346. const FORMAT_DD = 'DD';
  347. const FORMAT_D = 'D';
  348. const FORMAT_HH = 'HH';
  349. const FORMAT_H = 'H';
  350. const FORMAT_hh = 'hh';
  351. const FORMAT_h = 'h';
  352. const FORMAT_mm = 'mm';
  353. const FORMAT_m = 'm';
  354. const FORMAT_ss = 'ss';
  355. const FORMAT_s = 's';
  356. const FORMAT_A = 'A';
  357. const FORMAT_a = 'a';
  358. const FORMAT_KEYS = [
  359. { f: FORMAT_YYYY, k: 'year' },
  360. { f: FORMAT_MMMM, k: 'month' },
  361. { f: FORMAT_DDDD, k: 'day' },
  362. { f: FORMAT_MMM, k: 'month' },
  363. { f: FORMAT_DDD, k: 'day' },
  364. { f: FORMAT_YY, k: 'year' },
  365. { f: FORMAT_MM, k: 'month' },
  366. { f: FORMAT_DD, k: 'day' },
  367. { f: FORMAT_HH, k: 'hour' },
  368. { f: FORMAT_hh, k: 'hour' },
  369. { f: FORMAT_mm, k: 'minute' },
  370. { f: FORMAT_ss, k: 'second' },
  371. { f: FORMAT_M, k: 'month' },
  372. { f: FORMAT_D, k: 'day' },
  373. { f: FORMAT_H, k: 'hour' },
  374. { f: FORMAT_h, k: 'hour' },
  375. { f: FORMAT_m, k: 'minute' },
  376. { f: FORMAT_s, k: 'second' },
  377. { f: FORMAT_A, k: 'ampm' },
  378. { f: FORMAT_a, k: 'ampm' },
  379. ];
  380. const DAY_NAMES = [
  381. 'Sunday',
  382. 'Monday',
  383. 'Tuesday',
  384. 'Wednesday',
  385. 'Thursday',
  386. 'Friday',
  387. 'Saturday',
  388. ];
  389. const DAY_SHORT_NAMES = [
  390. 'Sun',
  391. 'Mon',
  392. 'Tue',
  393. 'Wed',
  394. 'Thu',
  395. 'Fri',
  396. 'Sat',
  397. ];
  398. const MONTH_NAMES = [
  399. 'January',
  400. 'February',
  401. 'March',
  402. 'April',
  403. 'May',
  404. 'June',
  405. 'July',
  406. 'August',
  407. 'September',
  408. 'October',
  409. 'November',
  410. 'December',
  411. ];
  412. const MONTH_SHORT_NAMES = [
  413. 'Jan',
  414. 'Feb',
  415. 'Mar',
  416. 'Apr',
  417. 'May',
  418. 'Jun',
  419. 'Jul',
  420. 'Aug',
  421. 'Sep',
  422. 'Oct',
  423. 'Nov',
  424. 'Dec',
  425. ];
  426. const VALID_AMPM_PREFIX = [
  427. FORMAT_hh, FORMAT_h, FORMAT_mm, FORMAT_m, FORMAT_ss, FORMAT_s
  428. ];
  429. //# sourceMappingURL=datetime-util.js.map