Skip to main content

TelephoneNumber - Java class


The TelephoneNumber class was designed to use the java.text.MessageFormat class to format a US phone number with the proper characters and spacing. The class excepts numbers any many different ways and parses them into it's internal data so that it can display the phone number in the standard way, i.e. (800) 555-1212. It can even accept an alpha number like "877 HOLY-COW" and with the right options format it as alpha or numbers.

The TelephoneNumber class represents a US telephone number.

This class contains many constructors for various uses. It then stores the telephone number internally in seperate codes (area code, exchange, etc.). This encourages use of the format method to output the telephone number in any style the programmer wishes.

[needs i18n work]

Example usage:
long number = 8005551212L;
TelephoneNumber phone = new TelephoneNumber(number);
StringBuffer msg = new StringBuffer("Call me at ");
msg.append(phone.format());
// msg is now "Call me at (800) 555-1212"


US Format:

The general US format is a 3 digit area code, a 3 digit exchange, a 4 digit station. Typically written (800) 555-1212. Area codes are concidered optional unless you live in a '10 digit' calling area as many people now do. In which case you may want to set the isTenDigitArea flag which removes the parenthesis from the String output ie Denver area code requires 10 digit dailing 303 555-1212.


International Format:

International phone numbers are often written in this format:
+CC-(N)AAA-EEE-SSSS.

This expresses the numbers used for both international and national long-distance calls. In the example, +CC indicates the country code, while (N) indicates the NDD. When dialing from outside the country, the NDD would not be used after dialing the country code; when dialing from within that country, the NDD would be used, but the country code would not. Where AAA indicates the area code, EEE indicates the exchange, and SSSS indicates the station.

Country Code:

The country code is the national prefix to be used when dialing TO that particular country FROM another country.

NDD Prefix: (National Direct Dialing)

The NDD prefix is the access code used to make a call WITHIN that country from one city to another (when calling another city in the same vicinity, this may not be necessary). The NDD is followed by the city/area code for the place you are calling.

IDD Prefix: (International Direct Dialing)

The IDD prefix is the international prefix needed to dial a call FROM a country TO another country. This is followed by the country code for the country you are calling. The IDD is not part of the telephone number - but is a property of the locale, or the 'dailing device'.

Outside Line Prefix:

The Outside line prefix is use inside some private branch exchange (PBX) to connect with the outer exchange/trunk. It is typically 9 in the average US company. This is not part of the telephone number - but once again the property of the locale, or the 'dailing device'.


/*
* Copyright (c) 2003 David A. Koontz
*    Licensed under the Open Software License version 2.0
*
*    Grant of Copyright License. Licensor hereby grants You a world-wide,
*    royalty-free, non-exclusive, perpetual, sublicenseable license to
*    do the following:

*     a) to reproduce the Original Work in copies;
*     b) to prepare derivative works ("Derivative Works") based upon
*        the Original Work;
*     c) to distribute copies of the Original Work and Derivative Works
*        to the public, with the proviso that copies of Original Work or
*        Derivative Works that You distribute shall be licensed under the
*        Open Software License;
*     d) to perform the Original Work publicly; and
*     e) to display the Original Work publicly.
*/

//package com..util;

import java.text.MessageFormat;

/**
* The TelephoneNumber class represents a US telephone number.
*
* This class contains many constructors for various uses. It then stores the
* telephone number internally in seperate codes (area code, exchange, etc.).
* This encourages use of the format method to output the
* telephone number in any style the programmer wishes.
*
* [needs i18n work]
*
* Example usage:
*

*       long number = 8005551212L;
*       TelephoneNumber phone = new TelephoneNumber(number);
*       StringBuffer msg = new StringBuffer("Call me at ");
*       msg.append(phone.format());
*       // msg is now "Call me at (800) 555-1212"
*

*
* US Format:
* The general US format is a 3 digit area code, a 3 digit exchange, a 4 digit
* station. Typically written (800) 555-1212.  Area codes are concidered
* optional unless you live in a '10 digit' calling area as many people now do.
* In which case you may want to set the isTenDigitArea flag which
* removes the parenthesis from the String output ie Denver area code
* requires 10 digit dailing 303 555-1212.
*
* International Format:
* International phone numbers are often written in this format:
*    +CC-(N)AAA-EEE-SSSS.   
* This expresses the numbers used for both international and
* national long-distance calls.  In the example, +CC indicates
* the country code, while (N) indicates the NDD.  When dialing
* from outside the country, the NDD would not be used after dialing
* the country code; when dialing from within that country, the NDD
* would be used, but the country code would not. Where AAA indicates
* the area code, EEE indicates the exchange, and SSSS indicates the
* station.
*
*
*
* Country Code:
* The country code is the national prefix to be used when dialing TO
* that particular country FROM another country.
*
*
* NDD Prefix: (National Direct Dialing)
* The NDD prefix is the access code used to make a call WITHIN
* that country from one city to another (when calling another city in
* the same vicinity, this may not be necessary).
* The NDD is followed by the city/area code for the place you are
* calling.
*
*
* IDD Prefix: (International Direct Dialing)
* The IDD prefix is the international prefix needed to dial a call
* FROM a country TO another country. This is
* followed by the country code for the country you are calling.
* The IDD is not part of the telephone number - but is a property of
* the locale, or the 'dailing device'.
*
* Outside Line Prefix:
* The Outside line prefix is use inside some private branch exchange (PBX)
* to connect with the outer exchange/trunk. It is typically 9 in the
* average US company.  This is not part of the telephone number - but
* once again the property of the locale, or the 'dailing device'.
*
*
*
* @author David A. Koontz mailto:dakoontz@yahoo.com">[dakoontz@yahoo.com]

* @version 1.0, 7/20/2003
* @see MessageFormat
* @see http://www.opensource.org/licenses/osl-2.0.php">Open Software License
version 2.0
*
*/
public class TelephoneNumber {

    // International direct dial code is not part of a telephone
    // number - it would be info in the locale that the dialer is in.
    /** National direct dial code */
    protected String ndd;             // NDD of US is 1; UK is 0
    /** Country code */
    protected String countryCode;     // Country code of US is 1; UK is 44
    /** Area code */
    protected String areaCode;
    /** Exchange */
    protected String exchange;
    /** Station */
    protected String station;
    /** Extension */
    protected String extension;
    /** Is phone number part of a ten digit dialing area. */
    protected boolean isTenDigitArea = false;
    /** Alphanumeric phone number */
    protected String alphaNumber;    // used when we store "(800) GOT MILK"
    /** Is phone number an alphanumberic */
    protected boolean isAlphaNumber = false;

    /** The default format pattern - US centric */
    protected String defaultPatternUS = "({2}) {3}-{4}";
    /** The default format pattern */
    protected String defaultPattern = defaultPatternUS;

    /**
     * Basic constructor.
     */
    public TelephoneNumber() {
        this(null, null, null, "555", "1212", null);
    }

    /**
     * General constructor.
     * Create +1-(1)(800) 555-1212 ext: 34
     *
     * @param countryCode    the country code (US is 1; UK is 44)
     * @param ndd            the national direct dial code (US is 1; UK is 0)
     * @param areaCode       the area code (or city code)
     * @param exchange       the exchange
     * @param station        the station
     * @param extension      the extension (inside the PBX)
     */
    public TelephoneNumber(String countryCode, String ndd, String areaCode, String exchange, String station, String extension) {
        if ( exchange == null )
                throw new IllegalArgumentException("null arg forms not allowed for 'exchange'");
        if ( station == null )
                throw new IllegalArgumentException("null arg forms not allowed for 'station'");
        this.countryCode = countryCode;
        this.ndd         = ndd;
        this.areaCode    = areaCode;
        this.exchange    = exchange;
        this.station     = station;
        this.extension   = extension;
    }

    /**
     * Create (800) 555-1212 ext: 34
     */
    public TelephoneNumber(String areaCode, String exchange, String station, String extension) {
        this(null, null, areaCode, exchange, station, extension);

    }

    /**
     * Create  555-1212 ext: 34
     */
    public TelephoneNumber( String exchange, String station, String extension) {
        this(null, null, null, exchange, station, extension);

    }

    /**
     * Create 555-1212
     */
    public TelephoneNumber( String exchange, String station) {
        this(null, null, null, exchange, station, null);

    }

    /**
     * Create 888 HOLY COW by using alphanumeric digits
     */
    public TelephoneNumber( boolean isAlphaNumeric, String alphaNumber) {
        this();
        this.isAlphaNumber = isAlphaNumeric;
        if ( isAlphaNumber == true ) {
            this.alphaNumber = alphaNumber;
            // parse it
            String[] nums = parse(convertFromAlpha(alphaNumber));
            // ignore country code & NDD
            this.areaCode = nums[1];
            this.exchange = nums[2];
            this.station  = nums[3];
            this.extension= nums[4];

        } else {
            // parse this also - assuming no alpha char.
            String[] nums = parse(alphaNumber);
            // ignore country code & NDD
            this.areaCode = nums[1];
            this.exchange = nums[2];
            this.station  = nums[3];
            this.extension= nums[4];
        }
    }

    /**
     * Create  (888) 555-1212 by parsing string
     */
    public TelephoneNumber( String str) {
        this();
        // parse the string into numbers array
        String[] nums = parse(str);
        // ignore country code & NDD
        this.areaCode = nums[1];
        this.exchange = nums[2];
        this.station  = nums[3];
        this.extension= nums[4];
    }

    /**
     * Create (479) 555-1212 by parsing a long integer
     */
    public TelephoneNumber(long number) {
        this();
        String[] nums = parse(number);

        // convert from longs to strings
        this.areaCode = nums[1];
        this.exchange = nums[2];
        this.station = nums[3];

    }

    /** Create 555-1212 via long integers
     */
    public TelephoneNumber( long exchange, long station) {
        this();
        // convert from longs to strings
        if (exchange > 0) {
            this.exchange = String.valueOf(exchange);
        }
        if (station > 0) {
            this.station = String.valueOf(station);
        }
    }

    /**
     * Create (479) 555-1212 via long integers
     */
    public TelephoneNumber(long areaCode, long exchange, long station) {
        this();
        // convert from longs to strings
        if (areaCode > 0) {
            this.areaCode = String.valueOf(areaCode);
        }
        if (exchange > 0) {
            this.exchange = String.valueOf(exchange);
        }
        if (station > 0) {
            this.station = String.valueOf(station);
        }
    }


    /**
     * Parse a string like "(888) 555-1212 x 68" into a phone number.
     * Requires area code.
     * Does not allow country codes etc.
     * US centric.
     */
    protected String[] parse( String str) {
        String[] numbers = new String[5];
        StringBuffer ndd = new StringBuffer();
        StringBuffer area = new StringBuffer();
        StringBuffer exch = new StringBuffer();
        StringBuffer stat = new StringBuffer();
        StringBuffer ext = new StringBuffer();
        char ch = ' ';
        int areaCount = 0;
        int exchCount = 0;
        int statCount = 0;

        if ( str != null && str.length()>0 ) {
            // for each char in string
            for (int i = 0; i < str.length(); i++) {
                ch = str.charAt(i);
                // only look at digits
                if ( Character.isDigit(ch) ) {
                    // this is only finding this pattern 123 123 1234 99...
                    if ( areaCount < 3 ) {
                        area.append(ch);
                        areaCount++;
                    } else if ( exchCount < 3 ) {
                        exch.append(ch);
                        exchCount++;
                    } else if ( statCount < 4 ) {
                        stat.append(ch);
                        statCount++;
                    } else {
                        ext.append(ch);
                    }
                    // doesnot work for "571 3345 ext 897"
                    //@todo - get better parser
                }


            }
        }
        numbers[0] = ndd.toString();
        numbers[1] = area.toString();
        numbers[2] = exch.toString();
        numbers[3] = stat.toString();
        numbers[4] = ext.toString();

        return numbers;
    }

    /**
     * Parse a long integer like 4795718080 into phone number.
     * Does not allow country codes or extensions.
     * US centric.
     */
    protected String[] parse(long number) {
        String[] nums = new String[5];
        long area = 0;
        long exch = 0;
        long stat = 0;
        // parse the long from right to left
        // assume US style phone number without extension
        // example: 8005551212 or 2368000
        if (number > 0) {
            if (number > 9999) {
                exch = number / 10000;
                stat = number - (exch * 10000);
                if ( exch > 999 ) {
                    area = exch / 1000;
                    exch = exch - (area * 1000);
                }
            }
        }
        // convert from longs to strings
        if (area > 0) {
            nums[1] = String.valueOf(area);
        }
        if (exch > 0) {
            nums[2] = String.valueOf(exch);
        }
        if (stat > 0) {
            nums[3] = String.valueOf(stat);
        }

        return nums;
    }

    /** Convert alphanumeric phone number to numeric. */
    protected static String convertFromAlpha(String alpha) {
        // If you don't want US style key pad - change it.
        return convertFromAlphaUS(alpha);
    }

    /** Convert alphanumeric phone number to numeric - US centric */
    protected static String convertFromAlphaUS(String alpha) {
        // convert a US alphanumeric number into numberic
        // example:  800 GOT MILK -> 800 468-6455
        // where the Alpha to Numberic Key Pad
        //
        //      1     2     3
        //           ABC   DEF
        //
        //      4     5     6
        //     GHI   JKL   MNO
        //
        //      7     8     9
        //    PQRS   TUV   WXYZ
        //
        //     *      0     #
        //

        // prep the alpha string
        StringBuffer sb = new StringBuffer(alpha.toUpperCase().trim());

        // for each char in the string
        for (int i = 0; i < sb.length(); i++) {
            char ch = sb.charAt(i);
            if ( Character.isDigit(ch) ) {
                ; // ignore it
            } else if ( ch == '(' || ch == ')' ) {
                ; // ignore them
            } else if ( ch == 'A' || ch == 'B' || ch == 'C' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '2');
            } else if ( ch == 'D' || ch == 'E' || ch == 'F' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '3');
            } else if ( ch == 'G' || ch == 'H' || ch == 'I' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '4');
            } else if ( ch == 'J' || ch == 'K' || ch == 'L' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '5');
            } else if ( ch == 'M' || ch == 'N' || ch == 'O' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '6');
            } else if ( ch == 'P' || ch == 'Q' || ch == 'R' || ch == 'S') {
                sb.deleteCharAt(i);
                sb.insert(i, '7');
            } else if ( ch == 'T' || ch == 'U' || ch == 'V' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '8');
            } else if ( ch == 'W' || ch == 'X' || ch == 'Y' || ch == 'Z' ) {
                sb.deleteCharAt(i);
                sb.insert(i, '9');
            } else {
                ; // ignore
            }

        }

        return sb.toString();
    }

    /**
     * Format the telephone number with the supplied MessageFormat pattern.
     * The pattern has 7 messageFormatElement arguments (0 - 6).
     *
     * argument 0 - ndd
     * argument 1 - countryCode
     * argument 2 - areaCode
     * argument 3 - exchange
     * argument 4 - station
     * argument 5 - extension
     * argument 6 - alphanumeric
     *
     * Examples:
     * "({2}) {3}-{4} ext {5}" gives "(800) 555-1212 ext 99"
     * "{2}.{3}.{4}" gives "800.555.1212"
     * "{6} [{2} {3}-{4}]" gives "888 HOLY COW [888 465-9269]"
     *
     * @param pattern    the format pattern to be used
     * @see MessageFormat
     *
     */
    public String format(String pattern) {
        // create objects array from telephone codes
        Object[] objects = {ndd, countryCode, areaCode, exchange, station, extension, alphaNumber};

        // create a MessageFormat with pattern
        MessageFormat mf = new MessageFormat(pattern);
        return mf.format(objects);
    }

    /**
     * Format the telephone number with the defaultPattern MessageFormat.
     * US centric.
     */
    public String format() {
        // create objects array from telephone codes
        Object[] objects = {ndd, countryCode, areaCode, exchange, station, extension, alphaNumber};

        // create a MessageFormat with default pattern
        MessageFormat mf = new MessageFormat(defaultPattern);
        return mf.format(objects);
    }

    /** Human readable output
     */
    public String toString() {
        return toStringUS();
    }

    /** US centric human readable output
     */
    public String toStringUS() {
        // use US convention: "(800) 555-1212 ext: 20"
        StringBuffer sb = new StringBuffer(20);
        if ( this.isAlphaNumber ) {
            // just spit back the string
            sb.append(this.alphaNumber);
            sb.append(" [").append(areaCode).append(" ").append(exchange).append(" ").append(station).append("]");
        } else {

            if (countryCode != null && countryCode.length() > 0) {
                // format country code as '+CC-'
                sb.append("+").append(countryCode).append("-");
            }
            if (ndd != null && ndd.length() > 0) {
                if (countryCode != null && countryCode.equals("1") ) {
                    // in the US we don't write both the country code & the NDD
                    ; // igonre the NDD
                } else {
                    // format NDD as '(N) '
                    sb.append("(").append(ndd).append(") ");
                }
            }

            if (areaCode != null && areaCode.length() > 0) {
                // we could use a java.text.Format - but noooooo
                // assume US style (000)
                if ( areaCode.length() == 1 ) {
                    if (isTenDigitArea == true) {
                        sb.append("00").append(areaCode).append(" ");
                    } else {
                        sb.append("(").append("00").append(areaCode).append(") ");
                    }
                } else if (areaCode.length() == 2 ) {
                    if (isTenDigitArea == true) {
                        sb.append("0").append(areaCode).append(" ");
                    } else {
                        sb.append("(").append("0").append(areaCode).append(") ");
                    }
                } else if (areaCode.length() == 3 ) {
                    if (isTenDigitArea == true) {
                        sb.append(areaCode).append(" ");
                    } else {
                        sb.append("(").append(areaCode).append(") ");
                    }
                } else {
                    // more than 3 digits? - OK whatever
                    if (isTenDigitArea == true) {
                        sb.append(areaCode).append(" ");
                    } else {
                        sb.append("(").append(areaCode).append(") ");
                    }
                }
            }

            // exchange - assume US style 000
            if ( exchange.length() == 1 ) {
                sb.append("00").append(exchange).append("-");
            } else if (exchange.length() == 2 ) {
                sb.append("0").append(exchange).append("-");
            } else if (exchange.length() == 3 ) {
                sb.append(exchange).append("-");
            } else {
                // more than 3 digits? - OK whatever
                sb.append(exchange).append("-");
            }

            // station - assume US style 0000
            if ( station.length() == 1 ) {
                sb.append("000").append(station);
            } else if (station.length() == 2 ) {
                sb.append("00").append(station);
            } else if (station.length() == 3 ) {
                sb.append("0").append(station);
            } else {
                sb.append(station);
            }

            if (extension != null && extension.length() > 0) {
                sb.append(" ext: ").append(extension);
            }
        }

        return sb.toString();
    }

    /** MAIN - a test stub */
    public static void main(String[] args) {
        // test it out
        TelephoneNumber  n1 = new TelephoneNumber(); // test null params
        TelephoneNumber  n2 = new TelephoneNumber(571L, 9999L); // test 2 longs
        TelephoneNumber  n3 = new TelephoneNumber(479L, 571L, 1003L); // test 3 longs
        TelephoneNumber  n4 = new TelephoneNumber(303L, 222L, 7800L);   // test ten digit dialing
                         n4.isTenDigitArea = true;

        TelephoneNumber  n5 = new TelephoneNumber("(888) 341-8876");  // test formated string
        TelephoneNumber  n6 = new TelephoneNumber(127, 345, 8765); // test 3 integers
        TelephoneNumber  n7 = new TelephoneNumber(true, "800 GOT MILK");  // test parsing Alpha
        TelephoneNumber  n8 = new TelephoneNumber(3L, 4L, 5L);     // test zero padding
        TelephoneNumber  n9 = new TelephoneNumber("1", "1", "479", "571", "8509", "40"); // test 6 strings
        TelephoneNumber n10 = new TelephoneNumber(9876543210L);    // test 1 long
        TelephoneNumber n11 = new TelephoneNumber(false, "/800/ 555-1212 x 0"); // test parsing Non-Alpha

        System.out.println("TelephoneNumber(): " + n1);
        System.out.println("TelephoneNumber(571L, 9999L): " + n2);
        System.out.println("TelephoneNumber(479L, 571L, 1003L): " + n3);
        System.out.println("TelephoneNumber(303L, 222L, 7800L): " + n4);
        System.out.println("TelephoneNumber(\"(888) 341-8876\"): " + n5);
        System.out.println("TelephoneNumber(127, 345, 8765): " + n6);
        System.out.println("TelephoneNumber(true, \"800 GOT MILK\"): " + n7);
        System.out.println("TelephoneNumber(3L, 4L, 5L): " + n8);
        System.out.println("TelephoneNumber(\"1\", \"1\", \"479\", \"571\", \"8509\", \"40\"): " + n9);
        System.out.println("TelephoneNumber(9876543210L): " + n10);
        System.out.println("TelephoneNumber(false, \"/800/ 555-1212 x 0\"): " + n11);
        System.out.println("TelephoneNumber.format(\"{6} [{2} {3}-{4}]\"): " + n7.format("{6} [{2} {3}-{4}]"));
        System.out.println("TelephoneNumber.format(): " + n9.format());
    }

    /******************************************************************/
    /***  Getter/Setter                                             ***/
    /******************************************************************/

    public String getNdd() {
        return ndd;
    }

    public void setNdd(String value) {
        ndd = value;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String value) {
        countryCode = value;
    }

    public String getAreaCode() {
        return areaCode;
    }

    public void setAreaCode(String value) {
        areaCode = value;
    }

    public String getExchange() {
        return exchange;
    }

    public void setExchange(String value) {
        exchange = value;
    }

    public String getStation() {
        return station;
    }

    public void setStation(String value) {
        station = value;
    }

    public String getExtension() {
        return extension;
    }

    public void setExtension(String value) {
        extension = value;
    }

    public boolean isTenDigitArea() {
        return isTenDigitArea;
    }

    public void setTenDigitArea(boolean value) {
        isTenDigitArea = value;
    }

    public String getAlphaNumber() {
        return alphaNumber;
    }

    public void setAlphaNumber(String value) {
        alphaNumber = value;
    }

    public boolean isAlphaNumber() {
        return isAlphaNumber;
    }

    public void setAlphaNumber(boolean value) {
        isAlphaNumber = value;
    }
}


Post a Comment

Most Popular on Agile Complexification Inverter

Software Development terms applied to Home Construction

Let's Invert the typically wrong headed view of Software Development project management as a construction project.  We can map it the other way just to see if it works... to have some fun, to explore the meaning of phrases we toss around quite frequently.


Normally Project Management terms come from a construction domain.  We are going to apply the lexicon of modern software to the construction of a home.  We will follow the construction project and meet some of the people doing the work.

This is a very small (8 homes from $600,000 skyward) program in my 30-40 year old neighborhood.

About 6 months ago I saw the programs landing page go up.  It gives casual observers and some of the stakeholders a general idea of the intent of the program.  And most importantly who to contact for additional information if you happen to be interested in their products.

The Refuge program has 8 product projects and has them running independently.  Yet much of their DevOps infrastructure has already b…

Where is Shakespeare When We Need Him?

We are desperately searching for a term for people that connotes the best of human kind.  The creative, sensing, combinatorial synergistic, empathic solutioning persons that have yet to been labeled with a role name that works.

Some of the old terms:
Staff, Workforce, Human Resource, My Team, Army, Company

Shakespeare created 1700 words in his time.  He mutated verbs to nouns, and vice-a-versa, transformed verbs into adjectives, and formed words from whole cloth never before heard.  This skill is rare, but there is a poet that can create the term we need in the twenty-first century.

What should this term define?

21st Century Human Resource; the generalizing specialist.

Yes, but what more?  What less?

Suggest your poetry in the comments, let us see if we cannot do 1/1700 as well as The Bard.

By-the-way; who create the phrase "coin a word"?



A TED Play List - How do you create new words
6:52
Erin McKeanGo ahead, make up new words! In this fun, short talk from TEDYouth, lexicographer Er…

a little feedback please...

some feedback please...
How do you like the new look and feel of our site?
  ___)  nah (I like the old one better - bring it back)
  _X_)  yeah (much cleaner and easy to navigate)



powered by Typeform
See Also:

One Dark and Stormy during a Hurricane

I'm from the Carolina's where legend has it that our family commonly just hunkered down in the home on the coast and waterways than to head for inland shelter. Now that's from the old school days of barely improved (read paved) roads. They counted a storms severity by how high on the back porch steps (about 15 - top to ground) the water reached.  I don't recommend this action in todays world of long range forecast and transportation options.

I do recommend a drink or two in a hotel bar, far far away.

This is the week that Harvey came ashore in Texas.  I live on a hill in the little old town of Grapevine outside Dallas and Fort Worth.  And thank you all for letting me know that a storm is coming... I didn't get out and walk Malibu before the rain hit, so I grabbed a hat and we went anyway.  Much nicer walk with the drizzle, I'd say.

I'll raise a glass to you - if you were not smart enough to do the responsible thing, at the last responsible moment.

I do re…

Innovation in the Automobile Industry

In the 1900s the automobile industry was the most important and innovation industry in the USA.  But one could question if this was good for our society in the long run.  And one could question if they actually innovated.

In the early 1900s there were few automobiles, very little infrastructure created to support the industry.  For example the road system was still designed for horse drawn wagons and the wagon wheel (remember a steal rim and wooden compression spoke wheel).  The future US Highways, or the 1950s Interstate Highway System at the cost of $425 billion were decades and many innovations away. There was no gas service station, there were however horse stables, farriers, and blacksmiths in each town along the roads.  There was no real "road map", there was no road naming system, like was created in 1926 - the United States Numbered Highway System.

The industry employees millions of people, and was a large factor in the economy of the USA.  It created or was created b…