Why a new type, why not just use a composite type?
Three reasons actually: • Composite types are inefficient, space-wise. They have gotten more efficient as the versions progress, but they still store a whole tuple-header on disk for each value. • Composite types cannot have custom input/output functions. In recent versions of PostgreSQL there is actually a default output for composite types but it’s still not nice enough to use normally. • Using a composite type you would either have to store the actual value of the tag, which is incredibly wasteful of disk space (those time zones names can get quite long), or store the OID and leave users with unreadable values (which wouldn’t survive a dump/restore). A base type allows you to completely hide these implementation details.