3 namespace Org\Mxchange\CoreFramework\Utils\Numbers;
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
10 use \InvalidArgumentException;
13 * A number utility class
15 * @author Roland Haeder <webmaster@ship-simu.org>
17 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2023 Core Developer Team
18 * @license GNU GPL 3.0 or any newer version
19 * @link http://www.ship-simu.org
21 * This program is free software: you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation, either version 3 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34 final class NumberUtils extends BaseFrameworkSystem {
36 * Private constructor, no instance needed. If PHP would have a static initializer ...
40 private function __construct () {
41 // Call parent constructor
42 parent::__construct(__CLASS__);
46 * Filter a given number into a localized number
48 * @param $value The raw float value from e.g. database
49 * @return $localized Localized value
50 * @throws InvalidArgumentException If a parameter has an invalid value
52 public static function doFilterFormatNumber (float $value) {
54 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('NUMBER-UTILS: value=%s - CALLED!', $value));
57 throw new InvalidArgumentException(sprintf('value=%s cannot be below zero', $value));
60 // Generate it from config and localize dependencies
61 switch (FrameworkBootstrap::getLanguageInstance()->getLanguageCode()) {
62 case 'de': // German format is a bit different to default
63 $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), ',', '.');
67 $localized = number_format($value, FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('decimals'), '.', ',');
72 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('NUMBER-UTILS: localized=%s - CALLED!', $localized));
77 * Filter a given GMT timestamp (non Uni* stamp!) to make it look more
78 * beatiful for web-based front-ends. If null is given a message id
79 * null_timestamp will be resolved and returned.
81 * @param $timestamp Timestamp to prepare (filter) for display
82 * @return $readable A readable timestamp
83 * @throws InvalidArgumentException If a parameter has an invalid value
85 public static function doFilterFormatTimestamp (string $timestamp = NULL) {
87 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('NUMBER-UTILS: timestamp[%s]=%s - CALLED!', gettype($timestamp), $timestamp));
88 if (empty($timestamp)) {
90 throw new InvalidArgumentException('Parameter "timestamp" is empty');
93 // Default value to return
96 // Is the timestamp null?
97 if (is_null($timestamp)) {
98 // Get a message string
99 $readable = FrameworkBootstrap::getLanguageInstance()->getMessage('null_timestamp');
101 switch (FrameworkBootstrap::getLanguageInstance()->getLanguageCode()) {
102 case 'de': // German format is a bit different to default
103 // Split the GMT stamp up
104 $dateTime = explode(' ', $timestamp );
105 $dateArray = explode('-', $dateTime[0]);
106 $timeArray = explode(':', $dateTime[1]);
108 // Construct the timestamp
109 $readable = sprintf(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('german_date_time'),
119 default: // Default is pass-through
120 $readable = $timestamp;
126 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('NUMBER-UTILS: readable=%s - EXIT!', $readable));
131 * Checks whether the given number is really a number (only chars 0-9).
133 * @param $num A string consisting only chars between 0 and 9
134 * @param $castValue Whether to cast the value to double. Do only use this to secure numbers from Requestable classes.
135 * @param $assertMismatch Whether to assert mismatches
136 * @return $formatted The (hopefully) secured numbered value
137 * @throws InvalidArgumentException If a parameter has an invalid value
139 public static function bigintval (string $num, bool $castValue = true, bool $assertMismatch = false) {
141 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('NUMBER-UTILS: num=%s,castValue=%d,assertMismatch=%d - CALLED!', $num, intval($castValue), intval($assertMismatch)));
144 throw new InvalidArgumentException('Parameter "num" is empty');
147 // Filter all numbers out
148 $formatted = preg_replace('/[^0123456789]/', '', $num);
151 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('NUMBER-UTILS: formatted=%s', $formatted));
152 if ($castValue === true) {
153 // Cast to biggest numeric type, int is not enough for this cast
154 $formatted = (double) $formatted;
157 // Assert only if requested
158 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('NUMBER-UTILS: formatted[%s]=%s', gettype($formatted), $formatted));
159 if ($assertMismatch === true) {
160 // Has the whole value changed?
161 assert(('' . $formatted . '' != '' . $num . '') && (!is_null($num)));
165 //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('NUMBER-UTILS: formatted[%s]=%s - EXIT!', gettype($formatted), $formatted));