smart_formatter.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /**
  2. * DevExtreme (viz/axes/smart_formatter.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. Object.defineProperty(exports, "__esModule", {
  11. value: true
  12. });
  13. exports.smartFormatter = smartFormatter;
  14. exports.formatRange = formatRange;
  15. var _format_helper = require("../../format_helper");
  16. var _format_helper2 = _interopRequireDefault(_format_helper);
  17. var _type = require("../../core/utils/type");
  18. var _date = require("../../core/utils/date");
  19. var _date2 = _interopRequireDefault(_date);
  20. var _math = require("../../core/utils/math");
  21. var _utils = require("../core/utils");
  22. function _interopRequireDefault(obj) {
  23. return obj && obj.__esModule ? obj : {
  24. "default": obj
  25. }
  26. }
  27. var _format = _format_helper2.default.format;
  28. var floor = Math.floor;
  29. var abs = Math.abs;
  30. var EXPONENTIAL = "exponential";
  31. var formats = ["fixedPoint", "thousands", "millions", "billions", "trillions", EXPONENTIAL];
  32. var dateUnitIntervals = ["millisecond", "second", "minute", "hour", "day", "month", "year"];
  33. function getDatesDifferences(prevDate, curDate, nextDate, tickFormat) {
  34. var prevDifferences;
  35. var nextDifferences;
  36. var dateUnitInterval;
  37. var dateUnitsLength = dateUnitIntervals.length;
  38. var i;
  39. var j;
  40. if ("week" === tickFormat) {
  41. tickFormat = "day"
  42. } else {
  43. if ("quarter" === tickFormat) {
  44. tickFormat = "month"
  45. } else {
  46. if ("shorttime" === tickFormat) {
  47. tickFormat = "hour"
  48. } else {
  49. if ("longtime" === tickFormat) {
  50. tickFormat = "second"
  51. }
  52. }
  53. }
  54. }
  55. var tickFormatIndex = dateUnitIntervals.indexOf(tickFormat);
  56. if (nextDate) {
  57. nextDifferences = _date2.default.getDatesDifferences(curDate, nextDate);
  58. prevDifferences = _date2.default.getDatesDifferences(curDate, prevDate);
  59. if (nextDifferences[tickFormat]) {
  60. for (i = dateUnitsLength - 1; i >= tickFormatIndex; i--) {
  61. dateUnitInterval = dateUnitIntervals[i];
  62. if (i === tickFormatIndex) {
  63. setDateUnitInterval(nextDifferences, tickFormatIndex + (nextDifferences.millisecond ? 2 : 1))
  64. } else {
  65. if (nextDifferences[dateUnitInterval]) {
  66. resetDateUnitInterval(nextDifferences, i);
  67. break
  68. }
  69. }
  70. }
  71. }
  72. } else {
  73. prevDifferences = _date2.default.getDatesDifferences(prevDate, curDate);
  74. for (i = dateUnitsLength - 1; i >= tickFormatIndex; i--) {
  75. dateUnitInterval = dateUnitIntervals[i];
  76. if (prevDifferences[dateUnitInterval]) {
  77. if (i - tickFormatIndex > 1) {
  78. for (j = tickFormatIndex + 1; j >= 0; j--) {
  79. resetDateUnitInterval(prevDifferences, j)
  80. }
  81. break
  82. } else {
  83. if (isDateTimeStart(curDate, dateUnitInterval)) {
  84. for (j = i - 1; j > 0; j--) {
  85. resetDateUnitInterval(prevDifferences, j)
  86. }
  87. break
  88. }
  89. }
  90. }
  91. }
  92. }
  93. return nextDate ? nextDifferences : prevDifferences
  94. }
  95. function isDateTimeStart(date, dateUnitInterval) {
  96. var unitNumbers = [date.getMilliseconds(), date.getSeconds(), date.getMinutes(), date.getHours(), date.getDate(), date.getMonth()];
  97. var unitIndex = dateUnitIntervals.indexOf(dateUnitInterval);
  98. var i;
  99. for (i = 0; i < unitIndex; i++) {
  100. if (4 === i && 1 !== unitNumbers[i] || 4 !== i && 0 !== unitNumbers[i]) {
  101. return false
  102. }
  103. }
  104. return true
  105. }
  106. function resetDateUnitInterval(differences, intervalIndex) {
  107. var dateUnitInterval = dateUnitIntervals[intervalIndex];
  108. if (differences[dateUnitInterval]) {
  109. differences[dateUnitInterval] = false;
  110. differences.count--
  111. }
  112. }
  113. function setDateUnitInterval(differences, intervalIndex) {
  114. var dateUnitInterval = dateUnitIntervals[intervalIndex];
  115. if (false === differences[dateUnitInterval]) {
  116. differences[dateUnitInterval] = true;
  117. differences.count++
  118. }
  119. }
  120. function getNoZeroIndex(str) {
  121. return str.length - parseInt(str).toString().length
  122. }
  123. function getTransitionTickIndex(ticks, value) {
  124. var i;
  125. var curDiff;
  126. var minDiff;
  127. var nearestTickIndex = 0;
  128. minDiff = abs(value - ticks[0]);
  129. for (i = 1; i < ticks.length; i++) {
  130. curDiff = abs(value - ticks[i]);
  131. if (curDiff < minDiff) {
  132. minDiff = curDiff;
  133. nearestTickIndex = i
  134. }
  135. }
  136. return nearestTickIndex
  137. }
  138. function splitDecimalNumber(value) {
  139. return value.toString().split(".")
  140. }
  141. function createFormat(type) {
  142. var formatter;
  143. if ((0, _type.isFunction)(type)) {
  144. formatter = type;
  145. type = null
  146. }
  147. return {
  148. type: type,
  149. formatter: formatter
  150. }
  151. }
  152. function smartFormatter(tick, options) {
  153. var tickInterval = options.tickInterval;
  154. var tickIntervalIndex;
  155. var tickIndex;
  156. var actualIndex;
  157. var stringTick = abs(tick).toString();
  158. var precision = 0;
  159. var typeFormat;
  160. var offset = 0;
  161. var separatedTickInterval;
  162. var indexOfFormat = 0;
  163. var indexOfTick = -1;
  164. var datesDifferences;
  165. var format = options.labelOptions.format;
  166. var ticks = options.ticks;
  167. var log10Tick;
  168. var prevDateIndex;
  169. var nextDateIndex;
  170. var isLogarithmic = "logarithmic" === options.type;
  171. if (1 === ticks.length && 0 === ticks.indexOf(tick) && !(0, _type.isDefined)(tickInterval)) {
  172. tickInterval = abs(tick) >= 1 ? 1 : (0, _math.adjust)(1 - abs(tick), tick)
  173. }
  174. if (!(0, _type.isDefined)(format) && "discrete" !== options.type && tick && (10 === options.logarithmBase || !isLogarithmic)) {
  175. if ("datetime" !== options.dataType && (0, _type.isDefined)(tickInterval)) {
  176. if (ticks.length && ticks.indexOf(tick) === -1) {
  177. indexOfTick = getTransitionTickIndex(ticks, tick);
  178. tickInterval = (0, _math.adjust)(abs(tick - ticks[indexOfTick]), tick)
  179. }
  180. separatedTickInterval = splitDecimalNumber(tickInterval);
  181. if (separatedTickInterval < 2) {
  182. separatedTickInterval = splitDecimalNumber(tick)
  183. }
  184. if (isLogarithmic) {
  185. log10Tick = (0, _utils.getAdjustedLog10)(abs(tick));
  186. if (log10Tick > 0) {
  187. typeFormat = formats[floor(log10Tick / 3)] || EXPONENTIAL
  188. } else {
  189. if (log10Tick < -4) {
  190. typeFormat = EXPONENTIAL
  191. } else {
  192. precision = void 0
  193. }
  194. }
  195. } else {
  196. if (separatedTickInterval.length > 1 && !(0, _type.isExponential)(tickInterval)) {
  197. precision = separatedTickInterval[1].length;
  198. typeFormat = formats[indexOfFormat]
  199. } else {
  200. if ((0, _type.isExponential)(tickInterval) && (stringTick.indexOf(".") !== -1 || (0, _type.isExponential)(tick))) {
  201. typeFormat = EXPONENTIAL;
  202. if (!(0, _type.isExponential)(tick)) {
  203. precision = abs(getNoZeroIndex(stringTick.split(".")[1]) - (0, _math.getExponent)(tickInterval) + 1)
  204. } else {
  205. precision = Math.max(abs((0, _math.getExponent)(tick) - (0, _math.getExponent)(tickInterval)), abs((0, _math.getPrecision)(tick) - (0, _math.getPrecision)(tickInterval)))
  206. }
  207. } else {
  208. tickIntervalIndex = floor((0, _utils.getAdjustedLog10)(tickInterval));
  209. actualIndex = tickIndex = floor((0, _utils.getAdjustedLog10)(abs(tick)));
  210. if (tickIndex - tickIntervalIndex >= 2) {
  211. actualIndex = tickIntervalIndex
  212. }
  213. indexOfFormat = floor(actualIndex / 3);
  214. offset = 3 * indexOfFormat;
  215. if (indexOfFormat < 5) {
  216. if (tickIntervalIndex - offset === 2 && tickIndex >= 3) {
  217. indexOfFormat++;
  218. offset = 3 * indexOfFormat
  219. }
  220. typeFormat = formats[indexOfFormat]
  221. } else {
  222. typeFormat = formats[formats.length - 1]
  223. }
  224. if (offset > 0) {
  225. separatedTickInterval = splitDecimalNumber(tickInterval / Math.pow(10, offset));
  226. if (separatedTickInterval[1]) {
  227. precision = separatedTickInterval[1].length
  228. }
  229. }
  230. }
  231. }
  232. }
  233. if (void 0 !== typeFormat || void 0 !== precision) {
  234. format = {
  235. type: typeFormat,
  236. precision: precision
  237. }
  238. }
  239. } else {
  240. if ("datetime" === options.dataType) {
  241. typeFormat = _date2.default.getDateFormatByTickInterval(tickInterval);
  242. if (options.showTransition && ticks.length) {
  243. indexOfTick = ticks.map(Number).indexOf(+tick);
  244. if (1 === ticks.length && 0 === indexOfTick) {
  245. typeFormat = _format_helper2.default.getDateFormatByTicks(ticks)
  246. } else {
  247. if (indexOfTick === -1) {
  248. prevDateIndex = getTransitionTickIndex(ticks, tick)
  249. } else {
  250. prevDateIndex = 0 === indexOfTick ? ticks.length - 1 : indexOfTick - 1;
  251. nextDateIndex = 0 === indexOfTick ? 1 : -1
  252. }
  253. datesDifferences = getDatesDifferences(ticks[prevDateIndex], tick, ticks[nextDateIndex], typeFormat);
  254. typeFormat = _format_helper2.default.getDateFormatByDifferences(datesDifferences, typeFormat)
  255. }
  256. }
  257. format = createFormat(typeFormat)
  258. }
  259. }
  260. }
  261. return _format(tick, format)
  262. }
  263. function getHighDiffFormat(diff) {
  264. var stop = false;
  265. for (var i in diff) {
  266. if (true === diff[i] || "hour" === i || stop) {
  267. diff[i] = false;
  268. stop = true
  269. } else {
  270. if (false === diff[i]) {
  271. diff[i] = true
  272. }
  273. }
  274. }
  275. return createFormat(_format_helper2.default.getDateFormatByDifferences(diff))
  276. }
  277. function getHighAndSelfDiffFormat(diff, interval) {
  278. var stop = false;
  279. for (var i in diff) {
  280. if (stop) {
  281. diff[i] = false
  282. } else {
  283. if (i === interval) {
  284. stop = true
  285. } else {
  286. diff[i] = true
  287. }
  288. }
  289. }
  290. return createFormat(_format_helper2.default.getDateFormatByDifferences(diff))
  291. }
  292. function formatDateRange(startValue, endValue, tickInterval) {
  293. var diff = getDatesDifferences(startValue, endValue);
  294. var typeFormat = _date2.default.getDateFormatByTickInterval(tickInterval);
  295. var diffFormatType = _format_helper2.default.getDateFormatByDifferences(diff, typeFormat);
  296. var diffFormat = createFormat(diffFormatType);
  297. var values = [];
  298. if (tickInterval in diff) {
  299. var rangeFormat = getHighAndSelfDiffFormat(getDatesDifferences(startValue, endValue), tickInterval);
  300. var value = _format(startValue, rangeFormat);
  301. if (value) {
  302. values.push(value)
  303. }
  304. } else {
  305. var _rangeFormat = getHighDiffFormat(getDatesDifferences(startValue, endValue));
  306. var highValue = _format(startValue, _rangeFormat);
  307. if (highValue) {
  308. values.push(highValue)
  309. }
  310. values.push("".concat(_format(startValue, diffFormat), " - ").concat(_format(endValue, diffFormat)))
  311. }
  312. return values.join(", ")
  313. }
  314. function processDateInterval(interval) {
  315. if ((0, _type.isObject)(interval)) {
  316. var dateUnits = Object.keys(interval);
  317. var sum = dateUnits.reduce(function(sum, k) {
  318. return interval[k] + sum
  319. }, 0);
  320. if (1 === sum) {
  321. var dateUnit = dateUnits.filter(function(k) {
  322. return 1 === interval[k]
  323. })[0];
  324. return dateUnit.slice(0, dateUnit.length - 1)
  325. }
  326. }
  327. return interval
  328. }
  329. function formatRange(startValue, endValue, tickInterval, _ref) {
  330. var dataType = _ref.dataType,
  331. type = _ref.type,
  332. logarithmBase = _ref.logarithmBase;
  333. if ("discrete" === type) {
  334. return ""
  335. }
  336. if ("datetime" === dataType) {
  337. return formatDateRange(startValue, endValue, processDateInterval(tickInterval))
  338. }
  339. var formatOptions = {
  340. ticks: [],
  341. type: type,
  342. dataType: dataType,
  343. tickInterval: tickInterval,
  344. logarithmBase: logarithmBase,
  345. labelOptions: {}
  346. };
  347. return "".concat(smartFormatter(startValue, formatOptions), " - ").concat(smartFormatter(endValue, formatOptions))
  348. }