🚀 No Weird Utils
🎯 Lightweight, fun-named utilities for number formatting, unit conversions, and Unix time handling - because nobody likes weird numbers!
No Weird Utils is a comprehensive Python package that makes working with numbers, units, and time a breeze. Say goodbye to cryptic variable names and hello to intuitive, powerful tools that just work.
✨ Features
📊 noWeirdNumbersPls - Smart Number Formatting
- 🌍 Flexible separators: Use any thousands/decimal separators (European style:
1.234.567,89) - 🎨 Multiple styles: Default, scientific, percentage, binary, hex, and even Roman numerals!
- 🔄 Bidirectional: Format numbers for display and parse them back to numeric types
- 📋 Batch processing: Handle individual numbers or entire collections (lists, tuples, sets)
- 🔧 Precision control:
set_decimals()function for precise decimal rounding - 🚀 Fluent Interface: Object-oriented
NotWeirdclass with chainable methods - 🎯 Smart Locale Support: Built-in
anglo()andnotAnglo()formatting presets - 🔗 Method Chaining: Combine operations like
.notAnglo().add_prefix('€').with_decimals(2) - 📝 Rich Properties: Access formatted values via properties like
.formatted,.raw_default, etc.
🔄 metricFTW - Universal Unit Converter
- 📏 Length: From picometers to light-years, millimeters to miles
- ⚖️ Mass: Picograms to tons, ounces to kilograms
- 📐 Area: Square millimeters to square miles, hectares to acres
- 🌊 Volume: Milliliters to barrels, gallons to liters
- 🏃 Speed: m/s to mph, km/h to knots
- ⚡ Energy: Joules to BTU, calories to kilowatt-hours
- 💨 Pressure: Pascals to atmospheres, PSI to bars
- 🔋 Power: Watts to horsepower, kilowatts to BTU/hour
- 🌡️ Temperature: Celsius, Fahrenheit, Kelvin, and Rankine
- 🚀 Batch conversions: Convert entire datasets at once
⏰ quanticTime - Intuitive Unix Time Handling
- 🕐 Smart parsing: Auto-detect common date/time formats
- 🌍 Timezone aware: Full pytz integration with 400+ timezones
- 🔄 Format flexibility: Parse and output in any format you need
- 📅 Date arithmetic: Add/subtract time periods effortlessly
- 📊 Relative formatting: "2 hours ago", "in 3 days", etc.
🚀 Quick Start
Installation
pip install noWeirdUtils
For enhanced features:
# With timezone support
pip install noWeirdUtils[timezone]
🎯 Number Formatting Examples
from noWeirdNumbersPls.format_number import format_number, deformat_number, set_decimals, NotWeird
# ═══════════════════════════════════════════════════════════════
# 🔥 NEW: Object-Oriented Fluent Interface with NotWeird Class
# ═══════════════════════════════════════════════════════════════
# Create a NotWeird instance with chainable methods
nw = NotWeird(1234567.89)
# Chain formatting operations - settings persist on the object
formatted = nw.notAnglo().add_prefix('€').with_decimals(2).default()
print(formatted) # "€1.234.567,89"
# Use different styles with the same settings
print(nw.percent()) # "€123456789,00%"
print(nw.scientific()) # "€1.234568e+06"
print(nw.binary()) # "€0b100101101011010000111"
# Temporary override without changing object settings
print(nw.default(prefix='$')) # "$1.234.567,89"
print(nw.default()) # "€1.234.567,89" (back to stored prefix)
# Rich property access for formatted values
print(nw.formatted) # "€1.234.567,89" (fully formatted with prefix/suffix)
print(nw.raw_default) # "1.234.567,89" (without prefix/suffix)
print(nw.formatted_percent) # "€123456789,00%"
print(nw.formatted_scientific) # "€1.234568e+06"
# Parse formatted strings back to NotWeird objects
parsed_nw = NotWeird.parse("€1.234.567,89", thou_sep='.', dec_sep=',', prefix='€')
print(parsed_nw.number) # 1234567.89
# Apply precise rounding to the underlying number
nw.precise(decimals=1) # Modifies the internal number
print(nw.number) # 1234567.9
# Quick locale switching
nw.anglo() # Switch to US/UK format (, for thousands, . for decimal)
print(nw.default()) # "€1,234,567.9"
nw.notAnglo() # Switch to European format (. for thousands, , for decimal)
print(nw.default()) # "€1.234.567,9"
# ═══════════════════════════════════════════════════════════════
# 📊 Traditional Function-Based API (Still Available)
# ═══════════════════════════════════════════════════════════════
# European-style formatting
number = 1234567.89
formatted = format_number(number, thou_sep='.', dec_sep=',')
print(formatted) # "1.234.567,89"
# Multiple styles
print(format_number(0.1234, style='percent')) # "12.34%"
print(format_number(1000000, style='scientific')) # "1.000000e+06"
print(format_number(255, style='hex')) # "0xff"
print(format_number(42, style='roman')) # "XLII"
# With prefix and suffix
price = format_number(1299.99, prefix='$', suffix=' USD', decimals=2)
print(price) # "$1,299.99 USD"
# Batch processing
prices = [99.99, 149.50, 1299.99]
formatted_prices = format_number(prices, prefix='€', thou_sep='.', dec_sep=',')
print(formatted_prices) # ['€99,99', '€149,50', '€1.299,99']
# Parse back to numbers
parsed = deformat_number("1.234.567,89", thou_sep='.', dec_sep=',')
print(parsed) # 1234567.89
# Parse with type enforcement
parsed_int = deformat_number("1.234", thou_sep='.', enforce_type=int)
print(parsed_int) # 1234
# Parse special formats
hex_number = deformat_number("0xff", style='hex')
print(hex_number) # 255
roman_number = deformat_number("XLII", style='roman')
print(roman_number) # 42
# Precise decimal control
precise = set_decimals(3.14159265359, decimals=3)
print(precise) # 3.142
# Works with strings too
precise_str = set_decimals("2.71828", decimals=2, force_float=True)
print(precise_str) # 2.72
🔄 Unit Conversion Examples
from metricFTW.converter import MetricFTW
converter = MetricFTW()
# Length conversions
print(converter.convert_longitude(100, 'cm', 'm')) # 1.0
print(converter.convert_longitude(1, 'mile', 'km')) # 1.609344
# Mass conversions
print(converter.convert_mass(1, 'kg', 'pound')) # 2.20462
print(converter.convert_mass(16, 'ounce', 'g')) # 453.592
# Temperature conversions
print(converter.convert_temperature(0, 'C', 'F')) # 32.0
print(converter.convert_temperature(100, 'C', 'K')) # 373.15
# Volume conversions
print(converter.convert_volume(1, 'gallon_us', 'l')) # 3.78541
print(converter.convert_volume(500, 'ml', 'cup')) # 2.083333
# Batch conversions
distances = [1, 5, 10, 26.2]
km_distances = converter.convert_longitude(distances, 'mile', 'km')
print(km_distances) # [1.609344, 8.04672, 16.09344, 42.164928]
# See all available conversions
converter.show_available_conversions(detailed=True)
⏰ Time Handling Examples
from quanticTime.core import QuanticTime
# Create from various sources
qt1 = QuanticTime(1640995200) # Unix timestamp
qt2 = QuanticTime.now() # Current time
qt3 = QuanticTime.today() # Today at midnight
qt4 = QuanticTime.from_string("2024-01-01 10:30:00", fmt="%Y-%m-%d %H:%M:%S")
# Auto-parse common formats
qt5 = QuanticTime("2024-01-01")
qt6 = QuanticTime("2024-01-01 15:30:00")
qt7 = QuanticTime("Jan 1, 2024")
# Format output
print(qt2.to_string("%Y-%m-%d %H:%M:%S"))
print(qt2.to_iso())
# Time arithmetic
future = qt2.add_seconds(3600) # Add 1 hour
past = qt2.add_days(-7) # Subtract 7 days
# Get datetime object with timezone
dt_santiago = qt2.to_datetime("America/Santiago")
dt_tokyo = qt2.to_datetime("Asia/Tokyo")
# Check properties
print(qt2.is_weekend())
start_day = qt2.start_of_day()
end_day = qt2.end_of_day()
# List available timezones
QuanticTime.print_timezones(show_common_only=True)
QuanticTime.print_timezones(filter_text="Chile", detailed=True)
📚 Detailed Documentation
🎨 Number Formatting Styles
| Style | Example Input | Example Output | Description |
|---|---|---|---|
default |
1234.56 |
"1,234.56" |
Standard formatting with separators |
scientific |
1234.56 |
"1.234560e+03" |
Scientific notation |
percent |
0.1234 |
"12.34%" |
Percentage format |
binary |
255 |
"0b11111111" |
Binary representation |
hex |
255 |
"0xff" |
Hexadecimal representation |
roman |
42 |
"XLII" |
Roman numerals (integers only) |
🔄 Supported Unit Categories
📏 Length Units
Metric: pm, nm, μm, mm, cm, dm, m, dam, hm, km Imperial/Other: inch, foot, yard, mile, nautical_mile, angstrom, mil, furlong, fathom, light_year, parsec, astronomical_unit
⚖️ Mass Units
Metric: pg, ng, μg, mg, cg, dg, g, dag, hg, kg, t Imperial/Other: ounce, pound, stone, ton_us, ton_uk, grain, dram, troy_ounce, carat, slug
📐 Area Units
Metric: mm², cm², dm², m², dam², hm², km² Imperial/Other: sqin, sqft, sqyd, acre, hectare, sqmile, barn, are, rood
🌊 Volume Units
Metric: mm³, cm³, dm³, m³, l, ml, cl, dl, dal, hl, kl Imperial/Other: gallon_us, gallon_uk, quart, pint, cup, fluid_ounce, cubic_inch, tablespoon, teaspoon, barrel_oil, bushel
🏃 Speed Units
Metric: mm/s, cm/s, m/s, km/h Imperial/Other: mph, knot, fps, mach
⚡ Energy Units
J, kJ, MJ, GJ, TJ, cal, kcal, Btu, kWh, eV, erg, therm, quad
💨 Pressure Units
Pa, kPa, MPa, bar, mbar, atm, psi, torr, mmHg, inHg
🔋 Power Units
W, kW, MW, GW, hp, Btu_h, cal_s, erg_s
⏰ Time Zone Support
QuanticTime supports 400+ time zones through pytz integration. Some examples:
- Americas:
America/New_York,America/Los_Angeles,America/Santiago,America/Mexico_City - Europe:
Europe/London,Europe/Paris,Europe/Berlin,Europe/Madrid - Asia:
Asia/Tokyo,Asia/Shanghai,Asia/Dubai,Asia/Kolkata - Oceania:
Australia/Sydney,Australia/Melbourne,Pacific/Auckland - Special:
UTC,GMT,US/Eastern,US/Pacific
🛠️ Advanced Usage
Custom Number Formatting Functions
from noWeirdNumbersPls.format_number import format_number, set_decimals, NotWeird
# ═══════════════════════════════════════════════════════════════
# 🔥 NEW: Advanced NotWeird Class Usage
# ═══════════════════════════════════════════════════════════════
def create_currency_formatter(currency="USD", european_style=False):
"""Factory function to create currency formatters with consistent settings."""
if european_style:
return NotWeird(0).notAnglo().add_prefix(f'{currency} ')
else:
return NotWeird(0).anglo().add_prefix(f'{currency}')
# Create reusable formatters
eur_formatter = create_currency_formatter("EUR", european_style=True)
usd_formatter = create_currency_formatter("USD", european_style=False)
# Use the formatters with different amounts
amounts = [1234.56, 9876.54, 15000.00]
for amount in amounts:
eur_formatter._number = amount # Update the number
usd_formatter._number = amount
print(f"EUR: {eur_formatter.with_decimals(2).default()}") # "EUR 1.234,56"
print(f"USD: {usd_formatter.with_decimals(2).default()}") # "USD1,234.56"
# Complex chaining example
nw = NotWeird(3.14159265359)
result = (nw.precise(decimals=3) # First apply precision
.notAnglo() # Then set European format
.add_prefix('π ≈ ') # Add mathematical prefix
.add_suffix(' (rounded)')) # Add descriptive suffix
print(result.default()) # "π ≈ 3,142 (rounded)"
# Working with collections using NotWeird
prices = [99.99, 149.50, 1299.99]
formatter = NotWeird(prices).notAnglo().add_prefix('€').with_decimals(2)
formatted_list = formatter.default()
print(formatted_list) # ['€99,99', '€149,50', '€1.299,99']
# Property-based access for different formats
sales_data = NotWeird(1234567.89).notAnglo().add_prefix('€')
print(f"Default: {sales_data.formatted}")
print(f"Percentage: {sales_data.formatted_percent}")
print(f"Scientific: {sales_data.formatted_scientific}")
print(f"Raw (no prefix): {sales_data.raw_default}")
# ═══════════════════════════════════════════════════════════════
# 📊 Traditional Function-Based Approach
# ═══════════════════════════════════════════════════════════════
def format_currency(amount, currency="USD", european_style=False):
"""Format currency with locale-specific rules."""
if european_style:
return format_number(amount, thou_sep='.', dec_sep=',',
prefix=f'{currency} ', decimals=2)
else:
return format_number(amount, thou_sep=',', dec_sep='.',
prefix=f'{currency}', decimals=2)
# European format
print(format_currency(1234.56, "EUR", european_style=True)) # "EUR 1.234,56"
# US format
print(format_currency(1234.56, "USD", european_style=False)) # "USD1,234.56"
# Use set_decimals for precise rounding
precise_number = set_decimals(3.14159265359, decimals=3)
print(precise_number) # 3.142
Chained Unit Conversions
from metricFTW.converter import MetricFTW
converter = MetricFTW()
# Convert a recipe from US to metric
ingredients = {
'flour': (2, 'cup'), # cups to grams (approximately)
'milk': (1, 'cup'), # cups to ml
'temperature': (350, 'F') # Fahrenheit to Celsius
}
# Note: For cooking conversions, you might want to use density conversions
flour_ml = converter.convert_volume(ingredients['flour'][0], 'cup', 'ml')
milk_ml = converter.convert_volume(ingredients['milk'][0], 'cup', 'ml')
temp_c = converter.convert_temperature(ingredients['temperature'][0], 'F', 'C')
print(f"Flour: {flour_ml} ml") # Flour: 480.0 ml
print(f"Milk: {milk_ml} ml") # Milk: 240.0 ml
print(f"Temperature: {temp_c}°C") # Temperature: 176.66666666666666°C
Complex Time Operations
from quanticTime.core import QuanticTime
# Create a meeting scheduler
meeting_utc = QuanticTime.from_string("2024-03-15 14:00:00", tz="UTC")
# Show meeting time in different time zones
timezones = ["America/New_York", "Europe/London", "Asia/Tokyo", "America/Santiago"]
for tz in timezones:
local_time = meeting_utc.to_datetime(tz)
formatted_time = meeting_utc.to_string('%Y-%m-%d %H:%M %Z', tz)
print(f"{tz}: {formatted_time}")
# Calculate time until meeting
now = QuanticTime.now()
time_diff = meeting_utc.difference(now)
hours_until = time_diff / 3600
if hours_until > 0:
print(f"Meeting in {hours_until:.1f} hours")
else:
print(f"Meeting was {abs(hours_until):.1f} hours ago")
# Working with time ranges
start_day = meeting_utc.start_of_day()
end_day = meeting_utc.end_of_day()
is_weekend = meeting_utc.is_weekend("America/Santiago")
🧪 Testing
The package includes comprehensive tests to ensure reliability and accuracy. For detailed testing information, see TESTING.md.
Quick Test Commands
# Install development dependencies
pip install pytest pytest-cov
# Run all tests
pytest tests/
# Run tests with verbose output
pytest tests/ -v
# Run with coverage report
pytest tests/ --cov=metricFTW --cov=noWeirdNumbersPls --cov=quanticTime --cov-report=html
# Use the convenient test runner
python run_tests.py --coverage --verbose
Test Coverage
Current test coverage:
- metricFTW: 75% coverage
- noWeirdNumbersPls: 58% coverage
- quanticTime: 89% coverage
- Overall: 73% coverage
Test Categories
- Unit Tests: Test individual functions and classes
- Integration Tests: Test component interactions
- Verification Tests: Test against known accurate values
- Property Tests: Test object properties and formatting
🤝 Contributing
We welcome contributions! Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run the tests (
python run_tests.py) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure:
- All tests pass
- New features include tests
- Code follows the existing style
- Documentation is updated as needed
Development Setup
# Clone the repository
git clone https://github.com/santiago897/no_weird_project.git
cd no_weird_project
# Install in development mode with all dependencies
poetry install --with test
# Or with pip
pip install -e .[test]
# Run tests
python run_tests.py
1. **Fork the repository**
2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
3. **Make your changes** and add tests
4. **Run the test suite**: `pytest tests/`
5. **Commit your changes**: `git commit -m 'Add amazing feature'`
6. **Push to the branch**: `git push origin feature/amazing-feature`
7. **Open a Pull Request**
### Development Setup
```bash
# Clone the repo
git clone https://github.com/santiago897/no_weird_project.git
cd no_weird_project
# Install with development dependencies
pip install -e .[timezone]
pip install pytest pytest-cov black flake8
# Run tests
pytest tests/
# Format code
black .
📋 Requirements
- Python 3.8+
- Optional dependencies:
pytz ^2025.2: For timezone support in quanticTime
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- pytz - Special thanks to Stuart Bishop and the pytz team for creating and maintaining this incredible timezone library. pytz provides accurate and up-to-date timezone calculations for Python, making QuanticTime's timezone conversions possible across 400+ timezones worldwide. Without pytz, handling timezone-aware datetime operations would be significantly more complex and error-prone.
- Poetry for elegant dependency management and packaging
- The Python community for inspiration, feedback, and continuous innovation
🔗 Links
- PyPI: https://pypi.org/project/no-weird-utils/
- GitHub: https://github.com/santiago897/no_weird_project
- Documentation: Coming soon!
- Issues: https://github.com/santiago897/no_weird_project/issues
Made with ❤️ by Santiago Matta
"Because life's too short for weird numbers!" 🎯
Metadata
Release files for noWeirdUtils 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| noweirdutils-0.2.0.tar.gz | 25.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| noweirdutils-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.6 kB
Release files / noweirdutils-0.2.0.tar.gz
| Download URL | noweirdutils-0.2.0.tar.gz |
|---|---|
| Size | 25.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9b6cfad9ad3070e0fc5bf2b276e6d4d148b0d2511a8ef9d1fc3adf01cad18930
|
|
BLAKE2b-256 checksum How to use checksums |
a66fb598b4676ba69898836b2aea43b3067e9d1ae0b39ac6d01a1dec4e320858
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.9.13
|
Release files / noweirdutils-0.2.0-py3-none-any.whl
| Download URL | noweirdutils-0.2.0-py3-none-any.whl |
|---|---|
| Size | 25.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
91b75449d86b547deae194c2ce3ac2e8d2b9a9d11017e19cd61f24e78d2ba683
|
|
BLAKE2b-256 checksum How to use checksums |
31e13c13a51380a3f192993484c22ba275731c3c8161c5c89ada25e2f0cd2bda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.9.13
|
Security for noWeirdUtils 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.