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 "));
+	}
+
+}