Mercurial Hosting > nabble
diff src/fschmidt/util/java/Money.java @ 68:00520880ad02
add fschmidt source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 05 Oct 2025 17:24:15 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fschmidt/util/java/Money.java Sun Oct 05 17:24:15 2025 -0600 @@ -0,0 +1,292 @@ +/* +Copyright (c) 2008 Franklin Schmidt <fschmidt@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package fschmidt.util.java; + +import java.io.Externalizable; +import java.io.ObjectInput; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectInputStream; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.ResultSet; +import java.math.BigDecimal; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import fschmidt.db.DbStorable; + + +public final class Money implements Comparable, Externalizable, DbStorable { + private static final int currentVersion = 0; + private static final long serialVersionUID = 0L; + + private /*final*/ long cents; + + public static Money read(ObjectInput in) + throws IOException + { + if( !in.readBoolean() ) + return null; + return new Money(in.readLong()); + } + + public static void write(ObjectOutput out,Money m) + throws IOException + { + if( m==null ) { + out.writeBoolean(false); + return; + } + out.writeBoolean(true); + out.writeLong(m.cents); + } + + public void writeExternal(ObjectOutput out) + throws IOException + { + out.writeInt(currentVersion); + out.writeLong(cents); + } + + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException + { + int ver = in.readInt(); + switch(ver) { + case 0: + cents = in.readLong(); + break; + default: + throw new RuntimeException(); + } + } + + public Money() {} // for Externalizable + + public Money(ObjectInput in) + throws IOException, ClassNotFoundException + { + cents = in.readInt(); + } + + public Money(long cents) { + this.cents = cents; + } + + private static final Pattern p = Pattern.compile(" *-?\\$? *[0-9,.]+ *"); + private static final Pattern pSub = Pattern.compile("[ \\$,]"); + + public Money(String val) + throws NumberFormatException + { + if( !p.matcher(val).matches() ) + throw new NumberFormatException("invalid format for money: '"+val+"'"); + Matcher mSub = pSub.matcher(val); + val = pSub.matcher(val).replaceAll(""); + cents = Math.round(Float.parseFloat(val)*100); + } + + public Money(double d) { + cents = (long)Math.round( (d *1000) / 10); + } + + public void setField(PreparedStatement stmt,int idx) + throws SQLException + { + stmt.setBigDecimal(idx,toBigDecimal()); + } + + public static void setMoneyNull(PreparedStatement stmt,int idx) + throws SQLException + { + stmt.setNull(idx,java.sql.Types.DECIMAL); + } + + public static void setMoney(PreparedStatement stmt,int idx,Money m) + throws SQLException + { + if( m==null ) { + setMoneyNull(stmt,idx); + } else { + m.setField(stmt,idx); + } + } + + public static Money getMoney(ResultSet rs,String columnName) + throws SQLException + { + Money m = new Money(rs,columnName); + return rs.wasNull() ? null : m; + } + + private Money(ResultSet rs,String columnName) + throws SQLException + { + cents = Math.round(rs.getFloat(columnName)*100); + } + + public boolean equals(Object obj) { + if( obj==null || !(obj instanceof Money) ) + return false; + Money m = (Money)obj; + return cents==m.cents; + } + + public int compareTo(Money val) { + return val != null ? + (cents < val.cents ? -1 : cents==val.cents ? 0 : 1) : + 0; + } + + public int compareTo(Object obj) { + return compareTo( (Money)obj ); + } + + public int hashCode() { + return (int)cents; + } + + public String toString() { + return toString("$"); + } + + public String toString(String currency) { + StringBuilder buf = new StringBuilder(); + buf.append( cents<0 ? -cents : cents ); + while( buf.length() < 3 ) + buf.insert(0,'0'); + buf.insert(buf.length()-2,'.'); + int start = buf.charAt(0)=='-' ? 1 : 0; + for( int i=buf.length()-6; i>start; i-=3 ) + buf.insert(i,','); + buf.insert(0,currency); + if( cents < 0 ) + buf.insert(0,'-'); + return buf.toString(); + } + + public String toSimpleString() { + StringBuilder buf = new StringBuilder(); + buf.append(cents); + while( buf.length() < 3 ) + buf.insert(0,'0'); + buf.insert(buf.length()-2,'.'); + + return buf.toString(); + } + + public boolean isZero() { + return cents==0; + } + + public Money min(Money val) { + return cents < val.cents ? this : val; + } + + public Money max(Money val) { + return cents > val.cents ? this : val; + } + + public Money add(Money val) { + return new Money(cents+val.cents); + } + + public Money subtract(Money val) { + return new Money(cents-val.cents); + } + + public Money multiply(int val) { + return new Money(cents*val); + } + + public Money multiply(float val) { + return new Money(Math.round(cents*val)); + } + + public Money multiply(double val) { + return new Money((long)Math.round(cents*val)); + } + + public double divide(Money val) { + if ((double)val.cents == 0) { + return Double.NaN; + } + return (double)cents/(double)val.cents; + } + + public Money divide(int val) { + return new Money(cents/val); + } + + public Money divideRoundingUp(int val) { + return new Money((cents+val-1)/val); + } + + public Money divide(float val) { + return new Money(Math.round(cents/val)); + } + + public Money divide(double val) { + return new Money((long)Math.round(cents/val)); + } + + public Money inc() { + return new Money(cents+1); + } + + public Money dec() { + return new Money(cents-1); + } + + public Money avg(Money val) { + return new Money((cents+val.cents)/2); + } + + public double doubleValue() { + return cents/100.0; + } + + public BigDecimal toBigDecimal() { + return BigDecimal.valueOf(cents,2); + } + + public long getCents() { + return cents; + } + + + public static final Money ZERO = new Money(0); + public static final Money MAX_VALUE = new Money(Integer.MAX_VALUE); + public static final Money MIN_VALUE = new Money(Integer.MIN_VALUE); + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + } + + public static void main(String[] args) { + System.out.println(new Money("z$1,234.56 ")); + } + +}