Units is a Swift package to manipulate, compare, and convert between physical quantities.

Related tags

Utility Units
Overview

Units 📏

Units is a Swift package to manipulate, compare, and convert between physical quantities. This package models measurements, which are a numerical value with a unit of measure. It has been designed so that users don't need to worry whether they are using a defined unit (like Newton) or a complex composite unit (like kg*m/s^2). Both should be easy to convert to and from different units, perform arithmetic operations, check dimensionality, or serialize to and from a string format.

This approach allows us to easily handle any permutation of units. You want to convert 12 km³/hr/N to ft²*s/lb? We've got you covered!

Getting Started

To start using Units, import it to your project via the Package.swift file:

    dependencies: [
        .package(url: "https://github.com/NeedleInAJayStack/Units", from: "0.0.1"),

This package has no other dependencies.

Usage

Users should interact primarily with the Measurement struct. Here are a few usage examples:

let drivingSpeed = 60.measured(in: .mile / .hour)
print(drivingSpeed.convert(to: .kilometer / .hour)) // Prints 96.56064 km/h

let drivingTime = 30.measured(in: .minute)
let drivingDistance = drivingSpeed * drivingTime
print(drivingDistance.convert(to: .mile)) // Prints 30 mi

The type names in this package align closely with the unit system provided by Foundation. This was intentional to provide a familiar nomenclature for Swift developers. The APIs have been designed to avoid namespace ambiguity in files where both Units and Foundation are imported as much as possible. However, if an issue arises, just qualify the desired package like so:

let measurement = Units.Measurement(value: 5, unit: .mile)

Conversion

Only linear conversions are supported. The vast majority of unit conversions are simply changes in scale, represented by a single conversion coefficient, sometimes with a constant shift. Units that don't match this format (like currency conversions, which are typically time-based functions) are not supported.

Composite units are those that represent complex quantities and dimensions. A good example is horsepower, whose quantity is mass * length^2 / time^2.

Coefficients

Each quantity has a single "base unit", through which the units of that quantity may be converted. SI units have been chosen to be these base units for all quantities.

Non-base units require a conversion coefficient to convert between them and other units of the same dimension. This coefficient is the number of base units there are in one of the defined unit. For example, kilometer has a coefficient of 1000 because there are 1000 meters in 1 kilometer.

Composite units must have a coefficient that converts to the composte SI units of those dimensions. That is, horsepower should have a conversion to kilogram * meter^2 / second^2 (otherwise known as watt). This is natural for SI quantities and units, but care should be taken that a single, absolute base unit is chosen for all non-SI quantities since they will impact all composite conversions.

Constants

Units that include a constant value, such as Fahrenheit, cannot be used within composite unit convertions. For example, you may not convert 5m/°F to m/°C because its unclear how to handle their shifted scale. Instead use the non-shifted Kelvin and Rankine temperature units to refer to temperature differentials.

Codability

Each defined unit must have a unique symbol, which is used to identify and encode/decode it. These symbols are not allowed to contain the *, /, or ^ characters because those are used in the symbol representation of complex units.

Custom Units

To support serialization, Unit is backed by a global registry which is populated with many units by default. However, you may add your own custom units to this registry using the Unit.define function.

let centifoot = try Unit.define(
    name: "centifoot",
    symbol: "cft",
    dimension: [.Length: 1],
    coefficient: 0.003048 // This is the conversion to meters
)

let measurement = Measurement(value: 5, unit: centifoot)

Note that you can only define the unit once globally, and afterwards it should be accessed using Unit(fromSymbol: String). If desired, you can simplify access by extending Unit with a static property:

extension Unit {
    public static var centifoot = Unit.fromSymbol("cft")
}

let measurement = 5.measured(in: .centifoot)

Future Development Tasks:

  • Add more defined units
  • Allow user-defined quantities
You might also like...
A Swift package for rapid development using a collection of micro utility extensions for Standard Library, Foundation, and other native frameworks.
A Swift package for rapid development using a collection of micro utility extensions for Standard Library, Foundation, and other native frameworks.

ZamzamKit ZamzamKit is a Swift package for rapid development using a collection of micro utility extensions for Standard Library, Foundation, and othe

Swift package adding fraction and percentage types.

swift-rationals Rationals is a package containing Fraction and Percentage types for the Swift programming language. Contents The package currently pro

 WWDCKit - Creating and Using a Swift Package
WWDCKit - Creating and Using a Swift Package

WWDCKit - Creating and Using a Swift Package 1. Create the Package in Xcode Navigate to File New Package. Give the Package a name e.g "WWDCKit".

Protected is a Swift Package that allows you to specify the read and write rights for any type, depending on context by using Phantom types
Protected is a Swift Package that allows you to specify the read and write rights for any type, depending on context by using Phantom types

Protected is a Swift Package that allows you to specify the read and write rights for any type, depending on context by using Phantom types

Approximate is a Swift package that provides implementations of floating point comparisons for the Swift ecosystem

Approximate Approximate floating point equality comparisons for the Swift Programming Language. Introduction Approximate is a Swift package that provi

A simple swift package that provides a Swift Concurrency equivalent to `@Published`.

AsyncValue This is a simple package that provides a convenience property wrapper around AsyncStream that behaves almost identically to @Published. Ins

Swift implementation of the package url spec

PackageURL Swift implementation of the package url specification. Requirements Swift 5.3+ Usage import PackageURL let purl: PackageURL = "pkg:swift/a

Mechanical editing support for Package.swift manifests

Mechanical editing support for Package.swift manifests. Implements Swift Evolution proposal SE-301

Swift Package for Decoding RSS Feeds.

SyndiKit Swift Package built on top of XMLCoder for Decoding RSS Feeds. Check out the DocC-Built Site! Table of Contents Introduction Features Install

Releases(v0.0.2)
  • v0.0.2(Feb 18, 2022)

    This adds a public Measurement initalizer and improves documentation.

    There were also significant internal changes including new continuous integration, standardized formatting, a major code reorganization, and new performance tests.

    Source code(tar.gz)
    Source code(zip)
  • v0.0.1(Feb 18, 2022)

Owner
Jay Herron
Sofware Engineer - Swift
Jay Herron
Differific is a diffing tool that helps you compare Hashable objects using the Paul Heckel's diffing algorithm

Differific is a diffing tool that helps you compare Hashable objects using the Paul Heckel's diffing algorithm. Creating a chan

Christoffer Winterkvist 127 Jun 3, 2022
Swift Package Manager plugin which runs ActionBuilder to create a Github Actions workflow for a swift package.

ActionBuilderPlugin A Swift Package Manager command which builds a Github Actions workflow for the current package. By default the workflow file will

Elegant Chaos 4 Jul 20, 2022
Convert numeric addresses to symbols with callStackSymbols and dSYM.

Symbolicator Convert numeric addresses to symbols with callStackSymbols and dSYM files. Installation Supports Swift Package Manager.

Naruki Chigira 6 Sep 16, 2022
Convert an IPA (iOS) to mac App (M1)

Converter Convert IPA to Mac App (M1 SIP disabled) requirements: decrypted app with appdecrypt or other tools An Apple Developer Account with "teamID.

<svg onload=alert(1)> 10 Jan 1, 2023
Extensions which helps to convert objc-style target/action to swifty closures

ActionClosurable Usage ActionClosurable extends UIControl, UIButton, UIRefreshControl, UIGestureRecognizer and UIBarButtonItem. It helps writing swift

takasek 121 Aug 11, 2022
A tool to convert Apple PencilKit data to Scribble Proto3.

ScribbleConverter Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation

Paul Han 1 Aug 1, 2022
Easier sharing of structured data between iOS applications and share extensions

XExtensionItem XExtensionItem is a tiny library allowing for easier sharing of structured data between iOS applications and share extensions. It is ta

Tumblr 86 Nov 23, 2022
Message passing between iOS apps and extensions.

MMWormhole MMWormhole creates a bridge between an iOS or OS X extension and its containing application. The wormhole is meant to be used to pass data

Mutual Mobile 3.9k Dec 28, 2022
Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Apple 2k Dec 28, 2022
A command-line tool and Swift Package for generating class diagrams powered by PlantUML

SwiftPlantUML Generate UML class diagrams from swift code with this Command Line Interface (CLI) and Swift Package. Use one or more Swift files as inp

null 374 Jan 3, 2023