1. Go to this page and download the library: Download andanteproject/measurement library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
andanteproject / measurement example snippets
use Andante\Measurement\Math\NumberFactory;
use Andante\Measurement\Quantity\Length\Metric\Meter;
use Andante\Measurement\Quantity\Length\Metric\Kilometer;
use Andante\Measurement\Quantity\Energy\Electric\KilowattHour;
use Andante\Measurement\Quantity\Volume\Metric\CubicMeter;
use Andante\Measurement\Unit\Length\MetricLengthUnit;
use Andante\Measurement\Unit\Energy\SIEnergyUnit;
use Andante\Measurement\Parser\Parser;
use Andante\Measurement\Parser\ParseOptions;
use Andante\Measurement\Formatter\Formatter;
use Andante\Measurement\Formatter\FormatOptions;
use Andante\Measurement\Formatter\FormatStyle;
use Andante\Measurement\Unit\SymbolNotation;
// Create quantities using unit-specific classes
$distance = Meter::of(NumberFactory::create('5000'));
$energy = KilowattHour::of(NumberFactory::create('150'));
// Convert to different units
$inKilometers = $distance->to(MetricLengthUnit::Kilometer); // 5 km
$inJoules = $energy->to(SIEnergyUnit::Joule); // 540,000,000 J
// Arithmetic operations
$doubled = $distance->multiplyBy(NumberFactory::create('2')); // 10000 m
$sum = $distance->add(Kilometer::of(NumberFactory::create('2'))); // 7000 m
$diff = $distance->subtract(Kilometer::of(NumberFactory::create('1'))); // 4000 m
$half = $distance->divideBy(NumberFactory::create('2')); // 2500 m
// Type-safe: incompatible types won't compile
// $distance->add($energy); // ❌ Type error!
// Auto-scale to the most readable unit
$largeDistance = Meter::of(NumberFactory::create('5000'));
$scaled = $largeDistance->autoScale(); // 5 km
// Parse from strings with options
$parser = Parser::global();
// Simple parsing (no options)
$parsed = $parser->parse('100 km');
// Parse with Italian locale (for number formatting)
$parsed = $parser->parse(
'1.234,56 m',
ParseOptions::fromLocale('it_IT')
); // Italian: 1234.56 m
// Parse with Italian locale (different number)
$parsed = $parser->parse(
'1.500,5 km',
ParseOptions::fromLocale('it_IT')
); // Italian: 1500.5 km
// Parse with default unit (for numbers without units)
$parsed = $parser->parse(
'100',
ParseOptions::create()
->withDefaultUnit(MetricLengthUnit::Meter)
); // 100 m
// Parse with custom thousand separator
$parsed = $parser->parse(
'1 234.56 m',
ParseOptions::create()
->withThousandSeparator(' ')
->withDecimalSeparator('.')
); // 1234.56 m
// Parse with custom decimal separator
$parsed = $parser->parse(
'1234,56 m',
ParseOptions::create()
->withDecimalSeparator(',')
); // 1234.56 m
// Parse with locale and default unit
$parsed = $parser->parse(
'1.500',
ParseOptions::fromLocale('it_IT')
->withDefaultUnit(MetricLengthUnit::Kilometer)
); // 1500 km
// Parse with all custom separators
$parsed = $parser->parse(
'1_234|56 m',
ParseOptions::create()
->withThousandSeparator('_')
->withDecimalSeparator('|')
); // 1234.56 m
// Format with options
$formatter = Formatter::global();
// Default formatting (short style with symbol)
echo $formatter->format($distance); // "5,000 m"
// Format with Italian locale
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
); // "5.000 m"
// Format with long style (translated unit names)
echo $formatter->format(
$distance,
FormatOptions::create()
->withStyle(FormatStyle::Long)
); // "5,000 meters"
// Format with long style and Italian locale
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
->withStyle(FormatStyle::Long)
); // "5.000 metri"
// Format with narrow style (no space)
echo $formatter->format(
$distance,
FormatOptions::create()
->withStyle(FormatStyle::Narrow)
); // "5,000m"
// Format with narrow style and Italian locale
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
->withStyle(FormatStyle::Narrow)
); // "5.000m"
// Format with value only (no unit)
echo $formatter->format(
$distance,
FormatOptions::create()
->withStyle(FormatStyle::ValueOnly)
); // "5,000"
// Format with unit symbol only
echo $formatter->format(
$distance,
FormatOptions::create()
->withStyle(FormatStyle::UnitSymbolOnly)
); // "m"
// Format with unit name only
echo $formatter->format(
$distance,
FormatOptions::create()
->withStyle(FormatStyle::UnitNameOnly)
); // "meters"
// Format with unit name only and Italian locale
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
->withStyle(FormatStyle::UnitNameOnly)
); // "metri"
// Format with fixed precision
echo $formatter->format(
$distance,
FormatOptions::create()
->withPrecision(2)
); // "5,000.00 m"
// Format with precision and Italian locale
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
->withPrecision(2)
); // "5.000,00 m"
// Format with precision and long style
echo $formatter->format(
$distance,
FormatOptions::create()
->withPrecision(3)
->withStyle(FormatStyle::Long)
); // "5,000.000 meters"
// Format with custom thousand separator
echo $formatter->format(
$distance,
FormatOptions::create()
->withThousandSeparator(' ')
); // "5 000 m"
// Format with custom decimal separator
$smallDistance = Meter::of(NumberFactory::create('1234.56'));
echo $formatter->format(
$smallDistance,
FormatOptions::create()
->withDecimalSeparator(',')
); // "1,234,56 m"
// Format with custom separators
echo $formatter->format(
$smallDistance,
FormatOptions::create()
->withThousandSeparator('_')
->withDecimalSeparator('|')
); // "1_234|56 m"
// Format with separate unit locale (Italian numbers, English units)
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
->withUnitLocale('en_US')
->withStyle(FormatStyle::Long)
); // "5.000 meters" (Italian numbers, English unit name)
// Format with IEEE symbol notation
$energy = KilowattHour::of(NumberFactory::create('150'));
echo $formatter->format(
$energy,
FormatOptions::create()
->withSymbolNotation(SymbolNotation::IEEE)
); // "150 kW·h"
// Format with ASCII symbol notation
echo $formatter->format(
$energy,
FormatOptions::create()
->withSymbolNotation(SymbolNotation::ASCII)
); // "150 kW*h"
// Format with Unicode symbol notation
$volume = CubicMeter::of(NumberFactory::create('1000000'));
echo $formatter->format(
$volume,
FormatOptions::create()
->withSymbolNotation(SymbolNotation::Unicode)
); // "1,000,000 m³"
// Format with multiple options combined
echo $formatter->format(
$smallDistance,
FormatOptions::fromLocale('it_IT')
->withStyle(FormatStyle::Long)
->withPrecision(2)
); // "1.234,56 metri"
// Format with all options
echo $formatter->format(
$distance,
FormatOptions::fromLocale('it_IT')
->withUnitLocale('en_US')
->withStyle(FormatStyle::Long)
->withPrecision(3)
->withSymbolNotation(SymbolNotation::Unicode)
); // "5.000,000 meters"
use Andante\Measurement\Quantity\Length\Length;
use Andante\Measurement\Quantity\Length\MetricLength;
use Andante\Measurement\Quantity\Length\Metric\Meter;
use Andante\Measurement\Unit\Length\MetricLengthUnit;
// Level 1: Generic - accepts any length unit (meters, feet, miles, etc.)
function calculateArea(Length $width, Length $height): Area {
return $width->multiply($height);
}
// Level 2: System-specific - only metric units allowed (meters, kilometers, etc.)
function europeanDistance(MetricLength $distance): void {
// Rejects imperial units like feet or miles at compile time
}
// Level 3: Unit-specific - only meters, nothing else
function precisionMeasurement(Meter $length): void {
// Even kilometers or centimeters are rejected
}
use Andante\Measurement\Math\NumberFactory;
use Andante\Measurement\Quantity\Length\Length;
use Andante\Measurement\Quantity\Length\MetricLength;
use Andante\Measurement\Quantity\Length\Metric\Meter;
use Andante\Measurement\Unit\Length\MetricLengthUnit;
use Andante\Measurement\Unit\Length\ImperialLengthUnit;
// Unit-specific class - most type-safe
$meter = Meter::of(NumberFactory::create('100'));
// Mid-level class with unit - system-constrained
$length = MetricLength::of(
NumberFactory::create('100'),
MetricLengthUnit::Kilometer
);
// Generic class with any unit - most flexible
$imperial = Length::of(
NumberFactory::create('5280'),
ImperialLengthUnit::Foot
);
use Andante\Measurement\Unit\Length\MetricLengthUnit;
use Andante\Measurement\Unit\Length\ImperialLengthUnit;
$meters = Meter::of(NumberFactory::create('1000'));
// Convert to another unit in the same dimension
$kilometers = $meters->to(MetricLengthUnit::Kilometer); // 1 km
$feet = $meters->to(ImperialLengthUnit::Foot); // 3280.84 ft
// Get the numeric value
echo $kilometers->getValue()->value(); // "1"
echo $kilometers->getUnit()->symbol(); // "km"
$a = Meter::of(NumberFactory::create('100'));
$b = Meter::of(NumberFactory::create('50'));
// Same-unit arithmetic
$sum = $a->add($b); // 150 m
$diff = $a->subtract($b); // 50 m
$scaled = $a->multiplyBy(NumberFactory::create('2')); // 200 m
$half = $a->divideBy(NumberFactory::create('2')); // 50 m
// Cross-unit arithmetic (auto-converts to left operand's unit)
$km = Kilometer::of(NumberFactory::create('1'));
$result = $km->add($a); // 1.1 km (100m converted to 0.1km)
use Andante\Measurement\Quantity\Length\Metric\Meter;
use Andante\Measurement\Quantity\Time\SI\Second;
use Andante\Measurement\Quantity\Mass\Metric\Kilogram;
// Length × Length = Area
$width = Meter::of(NumberFactory::create('5'));
$height = Meter::of(NumberFactory::create('3'));
$area = $width->multiply($height); // SquareMeter (15 m²)
// Length ÷ Time = Velocity
$distance = Meter::of(NumberFactory::create('100'));
$time = Second::of(NumberFactory::create('10'));
$velocity = $distance->divide($time); // MeterPerSecond (10 m/s)
// Mass × Acceleration = Force
$mass = Kilogram::of(NumberFactory::create('10'));
$accel = MeterPerSecondSquared::of(NumberFactory::create('9.8'));
$force = $mass->multiply($accel); // Newton (98 N)
// Automatically choose the most readable unit
$grams = Gram::of(NumberFactory::create('5000'));
$scaled = $grams->autoScale(); // Kilogram (5 kg)
$bytes = Byte::of(NumberFactory::create('1048576'));
$scaled = $bytes->autoScale(); // Megabyte (1 MB)
// Works with all quantity types
$watts = Watt::of(NumberFactory::create('1500000'));
$scaled = $watts->autoScale(); // Megawatt (1.5 MW)
use Andante\Measurement\Parser\Parser;
use Andante\Measurement\Parser\ParseOptions;
$parser = Parser::global();
// Simple parsing
$length = $parser->parse('100 km');
$energy = $parser->parse('5.5 kWh');
$temp = $parser->parse('25 °C');
// With locale (for number formatting)
$options = ParseOptions::fromLocale('it_IT');
$length = $parser->parse('1.234,56 m', $options); // Italian: 1234.56 m
$options = ParseOptions::fromLocale('en_US');
$length = $parser->parse('1,234.56 m', $options); // US: 1234.56 m
// With default unit (for numbers without units)
$options = ParseOptions::create()->withDefaultUnit(MetricLengthUnit::Meter);
$length = $parser->parse('100', $options); // 100 m
// Safe parsing (returns null on failure)
$result = $parser->tryParse('invalid'); // null
use Andante\Measurement\Formatter\Formatter;
use Andante\Measurement\Formatter\FormatOptions;
use Andante\Measurement\Formatter\FormatStyle;
$formatter = Formatter::global();
$length = Meter::of(NumberFactory::create('1500'));
// Default (short style with symbol)
echo $formatter->format($length); // "1,500 m"
// Long style with unit name
$options = FormatOptions::create()->withStyle(FormatStyle::Long);
echo $formatter->format($length, $options); // "1,500 meters"
// With locale
$options = FormatOptions::fromLocale('de_DE');
echo $formatter->format($length, $options); // "1.500 m"
// Long style with locale (translated unit names)
$options = FormatOptions::fromLocale('it_IT')->withStyle(FormatStyle::Long);
echo $formatter->format($length, $options); // "1.500 metri"
// Fixed precision
$options = FormatOptions::create()->withPrecision(2);
echo $formatter->format($length, $options); // "1,500.00 m"
// Narrow style (no space between number and unit)
$options = FormatOptions::create()->withStyle(FormatStyle::Narrow);
echo $formatter->format($length, $options); // "1,500m"
use Andante\Measurement\Registry\UnitRegistry;
$registry = UnitRegistry::global();
// Find a unit by symbol
$unit = $registry->findBySymbol('km'); // MetricLengthUnit::Kilometer
// Get the quantity class for a unit
$class = $registry->getQuantityClass(MetricLengthUnit::Meter); // Meter::class
// Get all units for a dimension
$lengthUnits = $registry->getUnitsForDimension(Length::instance());
// Get only metric units
$metricUnits = $registry->getMetricUnits(Length::instance());
use Andante\Measurement\Registry\ConversionFactorRegistry;
$registry = ConversionFactorRegistry::global();
// Get conversion rule for a unit
$rule = $registry->get(MetricLengthUnit::Kilometer);
// factor: 1000 (1 km = 1000 m)
// Temperature uses affine conversions (factor + offset)
$rule = $registry->get(TemperatureUnit::Celsius);
// factor: 1, offset: 273.15 (K = °C + 273.15)
use Andante\Measurement\Registry\ResultQuantityRegistry;
$registry = ResultQuantityRegistry::global();
// What class should Meter × Meter return?
$resultClass = $registry->getResultClass(
Meter::class,
new DimensionalFormula(length: 2) // L²
);
// Returns: MetricArea::class (preserves metric system)
use Andante\Measurement\Registry\FormulaUnitRegistry;
$registry = FormulaUnitRegistry::global();
// Default unit for velocity (L¹T⁻¹)
$unit = $registry->getDefaultUnit(new DimensionalFormula(length: 1, time: -1));
// Returns: MetricVelocityUnit::MeterPerSecond
// Imperial default
$unit = $registry->getDefaultUnit(
new DimensionalFormula(length: 1, time: -1),
UnitSystem::Imperial
);
// Returns: ImperialVelocityUnit::FootPerSecond
use Andante\Measurement\Contract\Registry\QuantityDefaultConfigProviderInterface;
use Andante\Measurement\Registry\UnitRegistry;
use Andante\Measurement\Registry\ConversionFactorRegistry;
use Andante\Measurement\Registry\ResultQuantityRegistry;
use Andante\Measurement\Registry\FormulaUnitRegistry;
final class MyQuantityProvider implements QuantityDefaultConfigProviderInterface
{
public function registerUnits(UnitRegistry $registry): void
{
// Register unit → quantity class mappings
}
public function registerConversionFactors(ConversionFactorRegistry $registry): void
{
// Register unit → base unit conversion factors
}
public function registerResultMappings(ResultQuantityRegistry $registry): void
{
// Register dimensional formula → result class mappings
}
public function registerFormulaUnits(FormulaUnitRegistry $registry): void
{
// Register dimensional formula → default unit mappings
}
}
// Register with all registries at once
$provider = MyQuantityProvider::global();
$provider->registerUnits(UnitRegistry::global());
$provider->registerConversionFactors(ConversionFactorRegistry::global());
$provider->registerResultMappings(ResultQuantityRegistry::global());
$provider->registerFormulaUnits(FormulaUnitRegistry::global());
use Andante\Measurement\Contract\DimensionInterface;
use Andante\Measurement\Dimension\DimensionalFormula;
final class Viscosity implements DimensionInterface
{
private static ?self $instance = null;
private static ?DimensionalFormula $formula = null;
private function __construct() {}
public static function instance(): self
{
return self::$instance ??= new self();
}
public function getFormula(): DimensionalFormula
{
// Dynamic viscosity: M¹L⁻¹T⁻¹ (kg/(m·s))
return self::$formula ??= new DimensionalFormula(
mass: 1,
length: -1,
time: -1
);
}
}
use Andante\Measurement\Contract\UnitInterface;
use Andante\Measurement\Unit\UnitSystem;
use Andante\Measurement\Unit\SymbolNotation;
enum ViscosityUnit: string implements UnitInterface
{
case PascalSecond = 'Pa·s';
case Poise = 'P';
case Centipoise = 'cP';
public function symbol(SymbolNotation $notation = SymbolNotation::Default): string
{
return match ($notation) {
SymbolNotation::ASCII => match ($this) {
self::PascalSecond => 'Pa*s',
self::Poise => 'P',
self::Centipoise => 'cP',
},
default => $this->value,
};
}
public function name(): string
{
return match ($this) {
self::PascalSecond => 'Pascal second',
self::Poise => 'Poise',
self::Centipoise => 'Centipoise',
};
}
public function dimension(): DimensionInterface
{
return Viscosity::instance();
}
public function system(): UnitSystem
{
return UnitSystem::SI;
}
}
use Andante\Measurement\Contract\QuantityInterface;
interface ViscosityInterface extends QuantityInterface
{
}
use Andante\Measurement\Contract\Math\NumberInterface;
use Andante\Measurement\Contract\UnitInterface;
use Andante\Measurement\Contract\QuantityFactoryInterface;
use Andante\Measurement\Contract\ConvertibleInterface;
use Andante\Measurement\Contract\ComparableInterface;
use Andante\Measurement\Contract\CalculableInterface;
use Andante\Measurement\Quantity\Trait\ConvertibleTrait;
use Andante\Measurement\Quantity\Trait\ComparableTrait;
use Andante\Measurement\Quantity\Trait\CalculableTrait;
use Andante\Measurement\Exception\InvalidUnitException;
// Unit-specific class
final class PascalSecond implements
ViscosityInterface,
QuantityFactoryInterface,
ConvertibleInterface,
ComparableInterface,
CalculableInterface
{
use ConvertibleTrait;
use ComparableTrait;
use CalculableTrait;
private function __construct(
private readonly NumberInterface $value,
private readonly UnitInterface $unit,
) {}
public static function of(NumberInterface $value): self
{
return new self($value, ViscosityUnit::PascalSecond);
}
public static function from(NumberInterface $value, UnitInterface $unit): self
{
if (ViscosityUnit::PascalSecond !== $unit) {
throw InvalidUnitException::forInvalidUnit($unit, ViscosityUnit::PascalSecond, self::class);
}
return new self($value, $unit);
}
public function getValue(): NumberInterface
{
return $this->value;
}
public function getUnit(): UnitInterface
{
return $this->unit;
}
}
use Andante\Measurement\Contract\Registry\QuantityDefaultConfigProviderInterface;
use Andante\Measurement\Converter\ConversionRule;
use Andante\Measurement\Math\NumberFactory;
final class ViscosityProvider implements QuantityDefaultConfigProviderInterface
{
private static ?self $instance = null;
private function __construct() {}
public static function global(): self
{
return self::$instance ??= new self();
}
private function getUnits(): array
{
return [
[ViscosityUnit::PascalSecond, PascalSecond::class, '1'],
[ViscosityUnit::Poise, Poise::class, '0.1'],
[ViscosityUnit::Centipoise, Centipoise::class, '0.001'],
];
}
public function registerUnits(UnitRegistry $registry): void
{
foreach ($this->getUnits() as [$unit, $quantityClass, $factor]) {
$registry->register($unit, $quantityClass);
}
}
public function registerConversionFactors(ConversionFactorRegistry $registry): void
{
foreach ($this->getUnits() as [$unit, $quantityClass, $factor]) {
$registry->register($unit, ConversionRule::factor(NumberFactory::create($factor)));
}
}
public function registerResultMappings(ResultQuantityRegistry $registry): void
{
$formula = Viscosity::instance()->getFormula();
foreach ($this->getUnits() as [$unit, $quantityClass, $factor]) {
$registry->register($quantityClass, $formula, DynamicViscosity::class);
}
$registry->registerGeneric($formula, DynamicViscosity::class);
}
public function registerFormulaUnits(FormulaUnitRegistry $registry): void
{
$registry->register(
Viscosity::instance()->getFormula(),
ViscosityUnit::PascalSecond
);
}
}
// In your application bootstrap
ViscosityProvider::global()->registerUnits(UnitRegistry::global());
ViscosityProvider::global()->registerConversionFactors(ConversionFactorRegistry::global());
ViscosityProvider::global()->registerResultMappings(ResultQuantityRegistry::global());
ViscosityProvider::global()->registerFormulaUnits(FormulaUnitRegistry::global());
// Now you can use your custom quantity!
$viscosity = PascalSecond::of(NumberFactory::create('0.001'));
$inCentipoise = $viscosity->to(ViscosityUnit::Centipoise); // 1 cP
use Andante\Measurement\Translation\TranslationLoader;
// Get or create a translation loader for your locale
$loader = new TranslationLoader('en');
// Register translations for your custom units
$loader->registerTranslation(ViscosityUnit::PascalSecond, [
'one' => 'pascal second',
'other' => 'pascal seconds',
]);
$loader->registerTranslation(ViscosityUnit::Poise, [
'one' => 'poise',
'other' => 'poise',
]);
$loader->registerTranslation(ViscosityUnit::Centipoise, [
'one' => 'centipoise',
'other' => 'centipoise',
]);
// Use the loader with the formatter
$formatter = new Formatter($loader);
// Convert to DateInterval
$hours = Hour::of(NumberFactory::create('2.5'));
$interval = $hours->toPhpDateInterval(); // PT2H30M
// Create from DateInterval
$interval = new \DateInterval('PT1H30M45S');
$seconds = Second::ofPhpDateInterval($interval);
// $seconds->getValue()->value() = '5445'
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.