<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,4 @@
 #include &quot;amount.h&quot;
-#include &quot;datetime.h&quot;
 #include &quot;util.h&quot;
 
 #include &lt;list&gt;
@@ -607,7 +606,7 @@ bool amount_t::realzero() const
   return mpz_sgn(MPZ(quantity)) == 0;
 }
 
-amount_t amount_t::value(const std::time_t moment) const
+amount_t amount_t::value(const datetime_t&amp; moment) const
 {
   if (quantity) {
     amount_t amt(commodity().value(moment));
@@ -999,7 +998,7 @@ void parse_commodity(std::istream&amp; in, std::string&amp; symbol)
 }
 
 void parse_annotations(std::istream&amp; in, amount_t&amp; price,
-		       std::time_t&amp; date, std::string&amp; tag)
+		       datetime_t&amp; date, std::string&amp; tag)
 {
   do {
     char buf[256];
@@ -1036,7 +1035,7 @@ void parse_annotations(std::istream&amp; in, amount_t&amp; price,
       else
 	throw new amount_error(&quot;Commodity date lacks closing bracket&quot;);
 
-      parse_date(buf, &amp;date);
+      date = buf;
     }
     else if (c == '(') {
       if (! tag.empty())
@@ -1073,7 +1072,7 @@ void amount_t::parse(std::istream&amp; in, unsigned char flags)
   std::string  symbol;
   std::string  quant;
   amount_t     price;
-  std::time_t  date = 0;
+  datetime_t   date;
   std::string  tag;
   unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS;
   bool         negative = false;
@@ -1378,7 +1377,7 @@ bool amount_t::valid() const
 }
 
 void amount_t::annotate_commodity(const amount_t&amp;    price,
-				  const std::time_t  date,
+				  const datetime_t&amp;  date,
 				  const std::string&amp; tag)
 {
   const commodity_t *	  this_base;
@@ -1401,7 +1400,7 @@ void amount_t::annotate_commodity(const amount_t&amp;    price,
   commodity_t * ann_comm =
     annotated_commodity_t::find_or_create
       (*this_base, ! price &amp;&amp; this_ann ? this_ann-&gt;price : price,
-       date == 0 &amp;&amp; this_ann ? this_ann-&gt;date : date,
+       ! date &amp;&amp; this_ann ? this_ann-&gt;date : date,
        tag.empty() &amp;&amp; this_ann ? this_ann-&gt;tag : tag);
   if (ann_comm)
     set_commodity(*ann_comm);
@@ -1435,7 +1434,8 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
   {
     new_comm = annotated_commodity_t::find_or_create
       (*ann_comm.ptr, _keep_price ? ann_comm.price : amount_t(),
-       _keep_date ? ann_comm.date : 0, _keep_tag ? ann_comm.tag : &quot;&quot;);
+       _keep_date ? ann_comm.date : datetime_t(),
+       _keep_tag ? ann_comm.tag : &quot;&quot;);
   } else {
     new_comm = commodity_t::find_or_create(ann_comm.base_symbol());
   }
@@ -1461,7 +1461,7 @@ amount_t amount_t::price() const
   return *this;
 }
 
-std::time_t amount_t::date() const
+datetime_t amount_t::date() const
 {
   if (commodity_ &amp;&amp; commodity_-&gt;annotated) {
     DEBUG_PRINT(&quot;amounts.commodities&quot;,
@@ -1473,7 +1473,8 @@ std::time_t amount_t::date() const
 }
 
 
-void commodity_base_t::add_price(const std::time_t date, const amount_t&amp; price)
+void commodity_base_t::add_price(const datetime_t&amp; date,
+				 const amount_t&amp;   price)
 {
   if (! history)
     history = new history_t;
@@ -1488,7 +1489,7 @@ void commodity_base_t::add_price(const std::time_t date, const amount_t&amp; price)
   }
 }
 
-bool commodity_base_t::remove_price(const std::time_t date)
+bool commodity_base_t::remove_price(const datetime_t&amp; date)
 {
   if (history) {
     history_map::size_type n = history-&gt;prices.erase(date);
@@ -1595,15 +1596,15 @@ commodity_t * commodity_t::find(const std::string&amp; symbol)
   return NULL;
 }
 
-amount_t commodity_base_t::value(const std::time_t moment)
+amount_t commodity_base_t::value(const datetime_t&amp; moment)
 {
-  std::time_t age = 0;
-  amount_t    price;
+  datetime_t age;
+  amount_t   price;
 
   if (history) {
     assert(history-&gt;prices.size() &gt; 0);
 
-    if (moment == 0) {
+    if (! moment) {
       history_map::reverse_iterator r = history-&gt;prices.rbegin();
       age   = (*r).first;
       price = (*r).second;
@@ -1615,7 +1616,7 @@ amount_t commodity_base_t::value(const std::time_t moment)
 	price = (*r).second;
       } else {
 	age = (*i).first;
-	if (std::difftime(moment, age) != 0) {
+	if (moment != age) {
 	  if (i != history-&gt;prices.begin()) {
 	    --i;
 	    age	  = (*i).first;
@@ -1633,7 +1634,7 @@ amount_t commodity_base_t::value(const std::time_t moment)
   if (updater &amp;&amp; ! (flags &amp; COMMODITY_STYLE_NOMARKET))
     (*updater)(*this, moment, age,
 	       (history &amp;&amp; history-&gt;prices.size() &gt; 0 ?
-		(*history-&gt;prices.rbegin()).first : 0), price);
+		(*history-&gt;prices.rbegin()).first : datetime_t()), price);
 
   return price;
 }
@@ -1665,14 +1666,14 @@ bool annotated_commodity_t::operator==(const commodity_t&amp; comm) const
 void
 annotated_commodity_t::write_annotations(std::ostream&amp;      out,
 					 const amount_t&amp;    price,
-					 const std::time_t  date,
+					 const datetime_t&amp;  date,
 					 const std::string&amp; tag)
 {
   if (price)
     out &lt;&lt; &quot; {&quot; &lt;&lt; price &lt;&lt; '}';
 
   if (date)
-    out &lt;&lt; &quot; [&quot; &lt;&lt; datetime_t(date) &lt;&lt; ']';
+    out &lt;&lt; &quot; [&quot; &lt;&lt; date &lt;&lt; ']';
 
   if (! tag.empty())
     out &lt;&lt; &quot; (&quot; &lt;&lt; tag &lt;&lt; ')';
@@ -1681,7 +1682,7 @@ annotated_commodity_t::write_annotations(std::ostream&amp;      out,
 commodity_t *
 annotated_commodity_t::create(const commodity_t&amp; comm,
 			      const amount_t&amp;    price,
-			      const std::time_t  date,
+			      const datetime_t&amp;  date,
 			      const std::string&amp; tag,
 			      const std::string&amp; mapping_key)
 {
@@ -1719,7 +1720,7 @@ annotated_commodity_t::create(const commodity_t&amp; comm,
 namespace {
   std::string make_qualified_name(const commodity_t&amp; comm,
 				  const amount_t&amp;    price,
-				  const std::time_t  date,
+				  const datetime_t&amp;  date,
 				  const std::string&amp; tag)
   {
     if (price &lt; 0)
@@ -1745,7 +1746,7 @@ namespace {
 commodity_t *
 annotated_commodity_t::find_or_create(const commodity_t&amp; comm,
 				      const amount_t&amp;    price,
-				      const std::time_t  date,
+				      const datetime_t&amp;  date,
 				      const std::string&amp; tag)
 {
   std::string name = make_qualified_name(comm, price, date, tag);
@@ -1862,9 +1863,9 @@ struct commodity_updater_wrap : public commodity_base_t::updater_t
   commodity_updater_wrap(PyObject * self_) : self(self_) {}
 
   virtual void operator()(commodity_base_t&amp; commodity,
-			  const std::time_t moment,
-			  const std::time_t date,
-			  const std::time_t last,
+			  const datetime_t&amp; moment,
+			  const datetime_t&amp; date,
+			  const datetime_t&amp; last,
 			  amount_t&amp;         price) {
     call_method&lt;void&gt;(self, &quot;__call__&quot;, commodity, moment, date, last, price);
   }</diff>
      <filename>amount.cc</filename>
    </modified>
    <modified>
      <diff>@@ -4,13 +4,13 @@
 #include &lt;map&gt;
 #include &lt;stack&gt;
 #include &lt;string&gt;
-#include &lt;ctime&gt;
 #include &lt;cctype&gt;
 #include &lt;iostream&gt;
 #include &lt;sstream&gt;
 #include &lt;cassert&gt;
 #include &lt;exception&gt;
 
+#include &quot;datetime.h&quot;
 #include &quot;debug.h&quot;
 #include &quot;error.h&quot;
 
@@ -81,8 +81,8 @@ class amount_t
   void set_commodity(commodity_t&amp; comm) {
     commodity_ = &amp;comm;
   }
-  void annotate_commodity(const amount_t&amp; price,
-			  const std::time_t  date = 0,
+  void annotate_commodity(const amount_t&amp;    price,
+			  const datetime_t&amp;  date = datetime_t(),
 			  const std::string&amp; tag  = &quot;&quot;);
   amount_t strip_annotations(const bool _keep_price = keep_price,
 			     const bool _keep_date  = keep_date,
@@ -91,7 +91,7 @@ class amount_t
     commodity_ = NULL;
   }
   amount_t price() const;
-  std::time_t date() const;
+  datetime_t date() const;
 
   bool null() const {
     return ! quantity &amp;&amp; ! commodity_;
@@ -253,7 +253,7 @@ class amount_t
     return ! (*this == num);
   }
 
-  amount_t value(const std::time_t moment) const;
+  amount_t value(const datetime_t&amp; moment) const;
 
   void abs() {
     if (*this &lt; 0)
@@ -297,7 +297,7 @@ class amount_t
 				      char * item_pool_end);
 
   friend void parse_annotations(std::istream&amp; in, amount_t&amp; price,
-				std::time_t&amp; date, std::string&amp; tag);
+				datetime_t&amp; date, std::string&amp; tag);
 };
 
 unsigned int sizeof_bigint_t();
@@ -356,8 +356,8 @@ inline std::istream&amp; operator&gt;&gt;(std::istream&amp; in, amount_t&amp; amt) {
 #define COMMODITY_STYLE_NOMARKET   0x0010
 #define COMMODITY_STYLE_BUILTIN    0x0020
 
-typedef std::map&lt;const std::time_t, amount_t&gt;  history_map;
-typedef std::pair&lt;const std::time_t, amount_t&gt; history_pair;
+typedef std::map&lt;const datetime_t, amount_t&gt;  history_map;
+typedef std::pair&lt;const datetime_t, amount_t&gt; history_pair;
 
 class commodity_base_t;
 
@@ -403,24 +403,24 @@ class commodity_base_t
 
   struct history_t {
     history_map	prices;
-    std::time_t	last_lookup;
-    std::time_t	bogus_time;
+    datetime_t	last_lookup;
+    datetime_t	bogus_time;
     history_t() : last_lookup(0), bogus_time(0) {}
   };
   history_t * history;
 
-  void	   add_price(const std::time_t date, const amount_t&amp; price);
-  bool	   remove_price(const std::time_t date);
-  amount_t value(const std::time_t moment = std::time(NULL));
+  void	   add_price(const datetime_t&amp; date, const amount_t&amp; price);
+  bool	   remove_price(const datetime_t&amp; date);
+  amount_t value(const datetime_t&amp; moment = datetime_t::now);
 
   class updater_t {
    public:
     virtual ~updater_t() {}
     virtual void operator()(commodity_base_t&amp; commodity,
-			    const std::time_t moment,
-			    const std::time_t date,
-			    const std::time_t last,
-			    amount_t&amp;         price) = 0;
+			    const datetime_t&amp; moment,
+			    const datetime_t&amp; date,
+			    const datetime_t&amp; last,
+			    amount_t&amp; price) = 0;
   };
   friend class updater_t;
 
@@ -543,13 +543,13 @@ class commodity_t
     return base-&gt;history;
   }
 
-  void add_price(const std::time_t date, const amount_t&amp; price) {
+  void add_price(const datetime_t&amp; date, const amount_t&amp; price) {
     return base-&gt;add_price(date, price);
   }
-  bool remove_price(const std::time_t date) {
+  bool remove_price(const datetime_t&amp; date) {
     return base-&gt;remove_price(date);
   }
-  amount_t value(const std::time_t moment = std::time(NULL)) const {
+  amount_t value(const datetime_t&amp; moment = datetime_t::now) const {
     return base-&gt;value(moment);
   }
 
@@ -562,7 +562,7 @@ class annotated_commodity_t : public commodity_t
   const commodity_t * ptr;
 
   amount_t    price;
-  std::time_t date;
+  datetime_t  date;
   std::string tag;
 
   explicit annotated_commodity_t() {
@@ -577,25 +577,26 @@ class annotated_commodity_t : public commodity_t
 
   static void write_annotations(std::ostream&amp;      out,
 				const amount_t&amp;    price,
-				const std::time_t  date,
+				const datetime_t&amp;  date,
 				const std::string&amp; tag);
 
  private:
   static commodity_t * create(const commodity_t&amp; comm,
 			      const amount_t&amp;    price,
-			      const std::time_t  date,
+			      const datetime_t&amp;  date,
 			      const std::string&amp; tag,
 			      const std::string&amp; mapping_key);
 
   static commodity_t * find_or_create(const commodity_t&amp; comm,
 				      const amount_t&amp;    price,
-				      const std::time_t  date,
+				      const datetime_t&amp;  date,
 				      const std::string&amp; tag);
 
   friend class amount_t;
 };
 
-inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, const commodity_t&amp; comm) {
+inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,
+				const commodity_t&amp; comm) {
   out &lt;&lt; comm.symbol();
   return out;
 }</diff>
      <filename>amount.h</filename>
    </modified>
    <modified>
      <diff>@@ -33,7 +33,7 @@ amount_t balance_t::amount(const commodity_t&amp; commodity) const
   return amount_t();
 }
 
-balance_t balance_t::value(const std::time_t moment) const
+balance_t balance_t::value(const datetime_t&amp; moment) const
 {
   balance_t temp;
 
@@ -57,18 +57,18 @@ balance_t balance_t::price() const
   return temp;
 }
 
-std::time_t balance_t::date() const
+datetime_t balance_t::date() const
 {
-  std::time_t temp = 0;
+  datetime_t temp;
 
   for (amounts_map::const_iterator i = amounts.begin();
        i != amounts.end();
        i++) {
-    std::time_t date = (*i).second.date();
-    if (temp == 0 &amp;&amp; date != 0)
+    datetime_t date = (*i).second.date();
+    if (! temp &amp;&amp; date)
       temp = date;
     else if (temp != date)
-      return 0;
+      return datetime_t();
   }
 
   return temp;</diff>
      <filename>balance.cc</filename>
    </modified>
    <modified>
      <diff>@@ -2,10 +2,8 @@
 #define _BALANCE_H
 
 #include &quot;amount.h&quot;
-#include &quot;datetime.h&quot;
 
 #include &lt;map&gt;
-#include &lt;ctime&gt;
 #include &lt;iostream&gt;
 
 namespace ledger {
@@ -428,11 +426,11 @@ class balance_t
     return true;
   }
 
-  amount_t    amount(const commodity_t&amp; commodity =
-		     *commodity_t::null_commodity) const;
-  balance_t   value(const std::time_t moment = now) const;
-  balance_t   price() const;
-  std::time_t date() const;
+  amount_t   amount(const commodity_t&amp; commodity =
+		    *commodity_t::null_commodity) const;
+  balance_t  value(const datetime_t&amp; moment = datetime_t::now) const;
+  balance_t  price() const;
+  datetime_t date() const;
 
   balance_t
   strip_annotations(const bool keep_price = amount_t::keep_price,
@@ -870,13 +868,13 @@ class balance_pair_t
 		   *commodity_t::null_commodity) const {
     return quantity.amount(commodity);
   }
-  balance_t value(const std::time_t moment = now) const {
+  balance_t value(const datetime_t&amp; moment = datetime_t::now) const {
     return quantity.value(moment);
   }
   balance_t price() const {
     return quantity.price();
   }
-  std::time_t date() const {
+  datetime_t date() const {
     return quantity.date();
   }
 </diff>
      <filename>balance.h</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,6 @@
 #include &quot;binary.h&quot;
 
 #include &lt;fstream&gt;
-#include &lt;ctime&gt;
 #include &lt;sys/stat.h&gt;
 
 #define TIMELOG_SUPPORT 1
@@ -12,9 +11,9 @@ namespace ledger {
 
 static unsigned long binary_magic_number = 0xFFEED765;
 #ifdef DEBUG_ENABLED
-static unsigned long format_version      = 0x00020609;
+static unsigned long format_version      = 0x0002060b;
 #else
-static unsigned long format_version      = 0x00020608;
+static unsigned long format_version      = 0x0002060a;
 #endif
 
 static account_t **	   accounts;
@@ -34,43 +33,83 @@ extern char *		   bigints_next;
 extern unsigned int	   bigints_index;
 extern unsigned int	   bigints_count;
 
+template &lt;typename T&gt;
+inline void read_binary_number_nocheck(std::istream&amp; in, T&amp; num) {
+  in.read((char *)&amp;num, sizeof(num));
+}
+
+template &lt;typename T&gt;
+inline T read_binary_number_nocheck(std::istream&amp; in) {
+  T num;
+  read_binary_number_nocheck(in, num);
+  return num;
+}
+
+template &lt;typename T&gt;
+inline void read_binary_number_nocheck(char *&amp; data, T&amp; num) {
+  num = *((T *) data);
+  data += sizeof(T);
+}
+
+template &lt;typename T&gt;
+inline T read_binary_number_nocheck(char *&amp; data) {
+  T num;
+  read_binary_number_nocheck(data, num);
+  return num;
+}
+
 #if DEBUG_LEVEL &gt;= ALPHA
-#define read_binary_guard(in, id) {		\
-  unsigned short guard;				\
-  in.read((char *)&amp;guard, sizeof(guard));	\
-  assert(guard == id);				\
+static void assert_failed() {
+  assert(0);
 }
+#define read_binary_guard(in, id)				\
+  if (read_binary_number_nocheck&lt;unsigned short&gt;(in) != id)	\
+      assert_failed();
 #else
 #define read_binary_guard(in, id)
 #endif
 
 template &lt;typename T&gt;
 inline void read_binary_number(std::istream&amp; in, T&amp; num) {
+  read_binary_guard(in, 0x2003);
   in.read((char *)&amp;num, sizeof(num));
+  read_binary_guard(in, 0x2004);
+}
+
+inline void read_binary_bool(std::istream&amp; in, bool&amp; num) {
+  read_binary_guard(in, 0x2005);
+  unsigned char val;
+  in.read((char *)&amp;val, sizeof(val));
+  num = val == 1;
+  read_binary_guard(in, 0x2006);
 }
 
 template &lt;typename T&gt;
 inline void read_binary_long(std::istream&amp; in, T&amp; num) {
+  read_binary_guard(in, 0x2001);
+
   unsigned char len;
-  in.read((char *)&amp;len, sizeof(unsigned char));
+  read_binary_number_nocheck(in, len);
 
   num = 0;
   unsigned char temp;
   if (len &gt; 3) {
-    in.read((char *)&amp;temp, sizeof(unsigned char));
+    read_binary_number_nocheck(in, temp);
     num |= ((unsigned long)temp) &lt;&lt; 24;
   }
   if (len &gt; 2) {
-    in.read((char *)&amp;temp, sizeof(unsigned char));
+    read_binary_number_nocheck(in, temp);
     num |= ((unsigned long)temp) &lt;&lt; 16;
   }
   if (len &gt; 1) {
-    in.read((char *)&amp;temp, sizeof(unsigned char));
+    read_binary_number_nocheck(in, temp);
     num |= ((unsigned long)temp) &lt;&lt; 8;
   }
 
-  in.read((char *)&amp;temp, sizeof(unsigned char));
+  read_binary_number_nocheck(in, temp);
   num |= ((unsigned long)temp);
+
+  read_binary_guard(in, 0x2002);
 }
 
 template &lt;typename T&gt;
@@ -80,6 +119,12 @@ inline T read_binary_number(std::istream&amp; in) {
   return num;
 }
 
+inline bool read_binary_bool(std::istream&amp; in) {
+  bool num;
+  read_binary_bool(in, num);
+  return num;
+}
+
 template &lt;typename T&gt;
 inline T read_binary_long(std::istream&amp; in) {
   T num;
@@ -92,10 +137,10 @@ inline void read_binary_string(std::istream&amp; in, std::string&amp; str)
   read_binary_guard(in, 0x3001);
 
   unsigned char len;
-  read_binary_number(in, len);
+  read_binary_number_nocheck(in, len);
   if (len == 0xff) {
     unsigned short slen;
-    read_binary_number(in, slen);
+    read_binary_number_nocheck(in, slen);
     char * buf = new char[slen + 1];
     in.read(buf, slen);
     buf[slen] = '\0';
@@ -114,8 +159,7 @@ inline void read_binary_string(std::istream&amp; in, std::string&amp; str)
   read_binary_guard(in, 0x3002);
 }
 
-inline std::string read_binary_string(std::istream&amp; in)
-{
+inline std::string read_binary_string(std::istream&amp; in) {
   std::string temp;
   read_binary_string(in, temp);
   return temp;
@@ -123,31 +167,46 @@ inline std::string read_binary_string(std::istream&amp; in)
 
 template &lt;typename T&gt;
 inline void read_binary_number(char *&amp; data, T&amp; num) {
+  read_binary_guard(data, 0x2003);
   num = *((T *) data);
   data += sizeof(T);
+  read_binary_guard(data, 0x2004);
+}
+
+inline void read_binary_bool(char *&amp; data, bool&amp; num) {
+  read_binary_guard(data, 0x2005);
+  unsigned char val = *((unsigned char *) data);
+  data += sizeof(unsigned char);
+  num = val == 1;
+  read_binary_guard(data, 0x2006);
 }
 
 template &lt;typename T&gt;
 inline void read_binary_long(char *&amp; data, T&amp; num) {
-  unsigned char len = *((unsigned char *)data++);
+  read_binary_guard(data, 0x2001);
+
+  unsigned char len;
+  read_binary_number_nocheck(data, len);
 
   num = 0;
   unsigned char temp;
   if (len &gt; 3) {
-    temp =  *((unsigned char *)data++);
+    read_binary_number_nocheck(data, temp);
     num |= ((unsigned long)temp) &lt;&lt; 24;
   }
   if (len &gt; 2) {
-    temp =  *((unsigned char *)data++);
+    read_binary_number_nocheck(data, temp);
     num |= ((unsigned long)temp) &lt;&lt; 16;
   }
   if (len &gt; 1) {
-    temp =  *((unsigned char *)data++);
+    read_binary_number_nocheck(data, temp);
     num |= ((unsigned long)temp) &lt;&lt; 8;
   }
 
-  temp =  *((unsigned char *)data++);
+  read_binary_number_nocheck(data, temp);
   num |= ((unsigned long)temp);
+
+  read_binary_guard(data, 0x2002);
 }
 
 template &lt;typename T&gt;
@@ -157,6 +216,12 @@ inline T read_binary_number(char *&amp; data) {
   return num;
 }
 
+inline bool read_binary_bool(char *&amp; data) {
+  bool num;
+  read_binary_bool(data, num);
+  return num;
+}
+
 template &lt;typename T&gt;
 inline T read_binary_long(char *&amp; data) {
   T num;
@@ -166,18 +231,15 @@ inline T read_binary_long(char *&amp; data) {
 
 inline void read_binary_string(char *&amp; data, std::string&amp; str)
 {
-#if DEBUG_LEVEL &gt;= ALPHA
-  unsigned short guard;
-  guard = *((unsigned short *) data);
-  data += sizeof(unsigned short);
-  assert(guard == 0x3001);
-#endif
+  read_binary_guard(data, 0x3001);
 
-  unsigned char len = *data++;
+  unsigned char len;
+  read_binary_number_nocheck(data, len);
   if (len == 0xff) {
-    unsigned short slen = *((unsigned short *) data);
-    str = std::string(data + sizeof(unsigned short), slen);
-    data += sizeof(unsigned short) + slen;
+    unsigned short slen;
+    read_binary_number_nocheck(data, slen);
+    str = std::string(data, slen);
+    data += slen;
   }
   else if (len) {
     str = std::string(data, len);
@@ -187,11 +249,7 @@ inline void read_binary_string(char *&amp; data, std::string&amp; str)
     str = &quot;&quot;;
   }
 
-#if DEBUG_LEVEL &gt;= ALPHA
-  guard = *((unsigned short *) data);
-  data += sizeof(unsigned short);
-  assert(guard == 0x3002);
-#endif
+  read_binary_guard(data, 0x3002);
 }
 
 inline std::string read_binary_string(char *&amp; data)
@@ -203,18 +261,15 @@ inline std::string read_binary_string(char *&amp; data)
 
 inline void read_binary_string(char *&amp; data, std::string * str)
 {
-#if DEBUG_LEVEL &gt;= ALPHA
-  unsigned short guard;
-  guard = *((unsigned short *) data);
-  data += sizeof(unsigned short);
-  assert(guard == 0x3001);
-#endif
+  read_binary_guard(data, 0x3001);
 
-  unsigned char len = *data++;
+  unsigned char len;
+  read_binary_number_nocheck(data, len);
   if (len == 0xff) {
-    unsigned short slen = *((unsigned short *) data);
-    new(str) std::string(data + sizeof(unsigned short), slen);
-    data += sizeof(unsigned short) + slen;
+    unsigned short slen;
+    read_binary_number_nocheck(data, slen);
+    new(str) std::string(data, slen);
+    data += slen;
   }
   else if (len) {
     new(str) std::string(data, len);
@@ -224,11 +279,7 @@ inline void read_binary_string(char *&amp; data, std::string * str)
     new(str) std::string(&quot;&quot;);
   }
 
-#if DEBUG_LEVEL &gt;= ALPHA
-  guard = *((unsigned short *) data);
-  data += sizeof(unsigned short);
-  assert(guard == 0x3002);
-#endif
+  read_binary_guard(data, 0x3002);
 }
 
 inline void read_binary_amount(char *&amp; data, amount_t&amp; amt)
@@ -251,13 +302,13 @@ inline void read_binary_value(char *&amp; data, value_t&amp; val)
 
   switch (val.type) {
   case value_t::BOOLEAN:
-    *((bool *) val.data) = read_binary_number&lt;char&gt;(data) == 1;
+    read_binary_bool(data, *((bool *) val.data));
     break;
   case value_t::INTEGER:
     read_binary_long(data, *((long *) val.data));
     break;
   case value_t::DATETIME:
-    read_binary_number(data, ((datetime_t *) val.data)-&gt;when);
+    read_binary_number(data, *((datetime_t *) val.data));
     break;
   case value_t::AMOUNT:
     read_binary_amount(data, *((amount_t *) val.data));
@@ -283,7 +334,7 @@ inline void read_binary_mask(char *&amp; data, mask_t *&amp; mask)
 
 inline void read_binary_value_expr(char *&amp; data, value_expr_t *&amp; expr)
 {
-  if (read_binary_number&lt;unsigned char&gt;(data) == 0) {
+  if (! read_binary_bool(data)) {
     expr = NULL;
     return;
   }
@@ -314,7 +365,7 @@ inline void read_binary_value_expr(char *&amp; data, value_expr_t *&amp; expr)
   case value_expr_t::F_ACCOUNT_MASK:
   case value_expr_t::F_SHORT_ACCOUNT_MASK:
   case value_expr_t::F_COMMODITY_MASK:
-    if (read_binary_number&lt;unsigned char&gt;(data) == 1)
+    if (read_binary_bool(data))
       read_binary_mask(data, expr-&gt;mask);
     break;
 
@@ -330,11 +381,11 @@ inline void read_binary_value_expr(char *&amp; data, value_expr_t *&amp; expr)
 
 inline void read_binary_transaction(char *&amp; data, transaction_t * xact)
 {
-  read_binary_long(data, xact-&gt;_date);
-  read_binary_long(data, xact-&gt;_date_eff);
+  read_binary_number(data, xact-&gt;_date);
+  read_binary_number(data, xact-&gt;_date_eff);
   xact-&gt;account = accounts[read_binary_long&lt;account_t::ident_t&gt;(data) - 1];
 
-  char flag = read_binary_number&lt;char&gt;(data);
+  unsigned char flag = read_binary_number&lt;unsigned char&gt;(data);
   if (flag == 0) {
     read_binary_amount(data, xact-&gt;amount);
   }
@@ -350,7 +401,7 @@ inline void read_binary_transaction(char *&amp; data, transaction_t * xact)
     read_binary_string(data, xact-&gt;amount_expr.expr);
   }
 
-  if (*data++ == 1) {
+  if (read_binary_bool(data)) {
     xact-&gt;cost = new amount_t;
     read_binary_amount(data, *xact-&gt;cost);
     read_binary_string(data, xact-&gt;cost_expr);
@@ -383,7 +434,7 @@ inline void read_binary_entry_base(char *&amp; data, entry_base_t * entry,
   entry-&gt;end_pos = read_binary_long&lt;unsigned long&gt;(data);
   read_binary_long(data, entry-&gt;end_line);
 
-  bool ignore_calculated = read_binary_number&lt;char&gt;(data) == 1;
+  bool ignore_calculated = read_binary_bool(data);
 
   for (unsigned long i = 0, count = read_binary_long&lt;unsigned long&gt;(data);
        i &lt; count;
@@ -400,8 +451,8 @@ inline void read_binary_entry(char *&amp; data, entry_t * entry,
 			      transaction_t *&amp; xact_pool, bool&amp; finalize)
 {
   read_binary_entry_base(data, entry, xact_pool, finalize);
-  read_binary_long(data, entry-&gt;_date);
-  read_binary_long(data, entry-&gt;_date_eff);
+  read_binary_number(data, entry-&gt;_date);
+  read_binary_number(data, entry-&gt;_date_eff);
   read_binary_string(data, &amp;entry-&gt;code);
   read_binary_string(data, &amp;entry-&gt;payee);
 }
@@ -449,8 +500,8 @@ inline void read_binary_commodity_base_extra(char *&amp; data,
   for (unsigned long i = 0, count = read_binary_long&lt;unsigned long&gt;(data);
        i &lt; count;
        i++) {
-    std::time_t when;
-    read_binary_long(data, when);
+    datetime_t when;
+    read_binary_number(data, when);
     amount_t amt;
     read_binary_amount(data, amt);
 
@@ -460,22 +511,19 @@ inline void read_binary_commodity_base_extra(char *&amp; data,
     if (! commodity-&gt;history)
       commodity-&gt;history = new commodity_base_t::history_t;
     commodity-&gt;history-&gt;prices.insert(history_pair(when, amt));
+
     read_history = true;
   }
   if (read_history)
-    read_binary_long(data, commodity-&gt;history-&gt;last_lookup);
+    read_binary_number(data, commodity-&gt;history-&gt;last_lookup);
 
-  unsigned char flag;
-
-  flag = read_binary_number&lt;unsigned char&gt;(data);
-  if (flag) {
+  if (read_binary_bool(data)) {
     amount_t amt;
     read_binary_amount(data, amt);
     commodity-&gt;smaller = new amount_t(amt);
   }
 
-  flag = read_binary_number&lt;unsigned char&gt;(data);
-  if (flag) {
+  if (read_binary_bool(data)) {
     amount_t amt;
     read_binary_amount(data, amt);
     commodity-&gt;larger = new amount_t(amt);
@@ -517,7 +565,7 @@ inline commodity_t * read_binary_commodity_annotated(char *&amp; data)
   read_binary_amount(data, amt);
   commodity-&gt;price = amt;
 
-  read_binary_long(data, commodity-&gt;date);
+  read_binary_number(data, commodity-&gt;date);
   read_binary_string(data, commodity-&gt;tag);
 
   return commodity;
@@ -584,7 +632,7 @@ unsigned int read_binary_journal(std::istream&amp;	    in,
 	 i++) {
       std::string path = read_binary_string(in);
       std::time_t old_mtime;
-      read_binary_long(in, old_mtime);
+      read_binary_number(in, old_mtime);
       struct stat info;
       stat(path.c_str(), &amp;info);
       if (std::difftime(info.st_mtime, old_mtime) &gt; 0)
@@ -618,7 +666,7 @@ unsigned int read_binary_journal(std::istream&amp;	    in,
   delete journal-&gt;master;
   journal-&gt;master = read_binary_account(data, journal, master);
 
-  if (read_binary_number&lt;bool&gt;(data))
+  if (read_binary_bool(data))
     journal-&gt;basket = accounts[read_binary_long&lt;account_t::ident_t&gt;(data) - 1];
 
   // Allocate the memory needed for the entries and transactions in
@@ -693,7 +741,7 @@ unsigned int read_binary_journal(std::istream&amp;	    in,
     commodity_t * commodity;
     std::string   mapping_key;
 
-    if (read_binary_number&lt;char&gt;(data) == 0) {
+    if (! read_binary_bool(data)) {
       commodity	  = read_binary_commodity(data);
       mapping_key = commodity-&gt;base-&gt;symbol;
     } else {
@@ -768,8 +816,8 @@ unsigned int read_binary_journal(std::istream&amp;	    in,
 
 bool binary_parser_t::test(std::istream&amp; in) const
 {
-  if (read_binary_number&lt;unsigned long&gt;(in) == binary_magic_number &amp;&amp;
-      read_binary_number&lt;unsigned long&gt;(in) == format_version)
+  if (read_binary_number_nocheck&lt;unsigned long&gt;(in) == binary_magic_number &amp;&amp;
+      read_binary_number_nocheck&lt;unsigned long&gt;(in) == format_version)
     return true;
 
   in.clear();
@@ -787,22 +835,36 @@ unsigned int binary_parser_t::parse(std::istream&amp;	in,
 			     journal, master);
 }
 
-#if DEBUG_LEVEL &gt;= ALPHA
-#define write_binary_guard(in, id) {		\
-  unsigned short guard = id;			\
-  out.write((char *)&amp;guard, sizeof(guard));	\
+template &lt;typename T&gt;
+inline void write_binary_number_nocheck(std::ostream&amp; out, T num) {
+  out.write((char *)&amp;num, sizeof(num));
 }
+
+#if DEBUG_LEVEL &gt;= ALPHA
+#define write_binary_guard(out, id)			\
+  write_binary_number_nocheck&lt;unsigned short&gt;(out, id)
 #else
 #define write_binary_guard(in, id)
 #endif
 
 template &lt;typename T&gt;
 inline void write_binary_number(std::ostream&amp; out, T num) {
+  write_binary_guard(out, 0x2003);
   out.write((char *)&amp;num, sizeof(num));
+  write_binary_guard(out, 0x2004);
+}
+
+inline void write_binary_bool(std::ostream&amp; out, bool num) {
+  write_binary_guard(out, 0x2005);
+  unsigned char val = num ? 1 : 0;
+  out.write((char *)&amp;val, sizeof(val));
+  write_binary_guard(out, 0x2006);
 }
 
 template &lt;typename T&gt;
 inline void write_binary_long(std::ostream&amp; out, T num) {
+  write_binary_guard(out, 0x2001);
+
   unsigned char len = 4;
   if (((unsigned long)num) &lt; 0x00000100UL)
     len = 1;
@@ -810,23 +872,26 @@ inline void write_binary_long(std::ostream&amp; out, T num) {
     len = 2;
   else if (((unsigned long)num) &lt; 0x01000000UL)
     len = 3;
-  out.write((char *)&amp;len, sizeof(unsigned char));
+  write_binary_number_nocheck&lt;unsigned char&gt;(out, len);
 
+  unsigned char temp;
   if (len &gt; 3) {
-    unsigned char temp = (((unsigned long)num) &amp; 0xFF000000UL) &gt;&gt; 24;
-    out.write((char *)&amp;temp, sizeof(unsigned char));
+    temp = (((unsigned long)num) &amp; 0xFF000000UL) &gt;&gt; 24;
+    write_binary_number_nocheck(out, temp);
   }
   if (len &gt; 2) {
-    unsigned char temp = (((unsigned long)num) &amp; 0x00FF0000UL) &gt;&gt; 16;
-    out.write((char *)&amp;temp, sizeof(unsigned char));
+    temp = (((unsigned long)num) &amp; 0x00FF0000UL) &gt;&gt; 16;
+    write_binary_number_nocheck(out, temp);
   }
   if (len &gt; 1) {
-    unsigned char temp = (((unsigned long)num) &amp; 0x0000FF00UL) &gt;&gt; 8;
-    out.write((char *)&amp;temp, sizeof(unsigned char));
+    temp = (((unsigned long)num) &amp; 0x0000FF00UL) &gt;&gt; 8;
+    write_binary_number_nocheck(out, temp);
   }
 
-  unsigned char temp = (((unsigned long)num) &amp; 0x000000FFUL);
-  out.write((char *)&amp;temp, sizeof(unsigned char));
+  temp = (((unsigned long)num) &amp; 0x000000FFUL);
+  write_binary_number_nocheck(out, temp);
+
+  write_binary_guard(out, 0x2002);
 }
 
 inline void write_binary_string(std::ostream&amp; out, const std::string&amp; str)
@@ -836,10 +901,10 @@ inline void write_binary_string(std::ostream&amp; out, const std::string&amp; str)
   unsigned long len = str.length();
   if (len &gt; 255) {
     assert(len &lt; 65536);
-    write_binary_number&lt;unsigned char&gt;(out, 0xff);
-    write_binary_number&lt;unsigned short&gt;(out, len);
+    write_binary_number_nocheck&lt;unsigned char&gt;(out, 0xff);
+    write_binary_number_nocheck&lt;unsigned short&gt;(out, len);
   } else {
-    write_binary_number&lt;unsigned char&gt;(out, len);
+    write_binary_number_nocheck&lt;unsigned char&gt;(out, len);
   }
 
   if (len)
@@ -864,13 +929,13 @@ void write_binary_value(std::ostream&amp; out, const value_t&amp; val)
 
   switch (val.type) {
   case value_t::BOOLEAN:
-    write_binary_number&lt;char&gt;(out, *((bool *) val.data) ? 1 : 0);
+    write_binary_bool(out, *((bool *) val.data));
     break;
   case value_t::INTEGER:
     write_binary_long(out, *((long *) val.data));
     break;
   case value_t::DATETIME:
-    write_binary_number(out, ((datetime_t *) val.data)-&gt;when);
+    write_binary_number(out, *((datetime_t *) val.data));
     break;
   case value_t::AMOUNT:
     write_binary_amount(out, *((amount_t *) val.data));
@@ -891,11 +956,10 @@ void write_binary_mask(std::ostream&amp; out, mask_t * mask)
 void write_binary_value_expr(std::ostream&amp; out, const value_expr_t * expr)
 {
   if (! expr) {
-    write_binary_number&lt;unsigned char&gt;(out, 0);
+    write_binary_bool(out, false);
     return;
   }
-  write_binary_number&lt;unsigned char&gt;(out, 1);
-
+  write_binary_bool(out, true);
   write_binary_number(out, expr-&gt;kind);
 
   if (expr-&gt;kind &gt; value_expr_t::TERMINALS)
@@ -917,10 +981,10 @@ void write_binary_value_expr(std::ostream&amp; out, const value_expr_t * expr)
   case value_expr_t::F_SHORT_ACCOUNT_MASK:
   case value_expr_t::F_COMMODITY_MASK:
     if (expr-&gt;mask) {
-      write_binary_number&lt;char&gt;(out, 1);
+      write_binary_bool(out, true);
       write_binary_mask(out, expr-&gt;mask);
     } else {
-      write_binary_number&lt;char&gt;(out, 0);
+      write_binary_bool(out, false);
     }
     break;
 
@@ -935,36 +999,36 @@ void write_binary_value_expr(std::ostream&amp; out, const value_expr_t * expr)
 void write_binary_transaction(std::ostream&amp; out, transaction_t * xact,
 			      bool ignore_calculated)
 {
-  write_binary_long(out, xact-&gt;_date);
-  write_binary_long(out, xact-&gt;_date_eff);
+  write_binary_number(out, xact-&gt;_date);
+  write_binary_number(out, xact-&gt;_date_eff);
   write_binary_long(out, xact-&gt;account-&gt;ident);
 
   if (ignore_calculated &amp;&amp; xact-&gt;flags &amp; TRANSACTION_CALCULATED) {
-    write_binary_number&lt;char&gt;(out, 0);
+    write_binary_number&lt;unsigned char&gt;(out, 0);
     write_binary_amount(out, amount_t());
   }
   else if (xact-&gt;amount_expr) {
-    write_binary_number&lt;char&gt;(out, 2);
+    write_binary_number&lt;unsigned char&gt;(out, 2);
     write_binary_value_expr(out, xact-&gt;amount_expr.get());
     write_binary_string(out, xact-&gt;amount_expr.expr);
   }
   else if (! xact-&gt;amount_expr.expr.empty()) {
-    write_binary_number&lt;char&gt;(out, 1);
+    write_binary_number&lt;unsigned char&gt;(out, 1);
     write_binary_amount(out, xact-&gt;amount);
     write_binary_string(out, xact-&gt;amount_expr.expr);
   }
   else {
-    write_binary_number&lt;char&gt;(out, 0);
+    write_binary_number&lt;unsigned char&gt;(out, 0);
     write_binary_amount(out, xact-&gt;amount);
   }
 
   if (xact-&gt;cost &amp;&amp;
       (! (ignore_calculated &amp;&amp; xact-&gt;flags &amp; TRANSACTION_CALCULATED))) {
-    write_binary_number&lt;char&gt;(out, 1);
+    write_binary_bool(out, true);
     write_binary_amount(out, *xact-&gt;cost);
     write_binary_string(out, xact-&gt;cost_expr);
   } else {
-    write_binary_number&lt;char&gt;(out, 0);
+    write_binary_bool(out, false);
   }
 
   write_binary_number(out, xact-&gt;state);
@@ -994,7 +1058,7 @@ void write_binary_entry_base(std::ostream&amp; out, entry_base_t * entry)
       break;
     }
 
-  write_binary_number&lt;char&gt;(out, ignore_calculated ? 1 : 0);
+  write_binary_bool(out, ignore_calculated);
 
   write_binary_long(out, entry-&gt;transactions.size());
   for (transactions_list::const_iterator i = entry-&gt;transactions.begin();
@@ -1006,8 +1070,8 @@ void write_binary_entry_base(std::ostream&amp; out, entry_base_t * entry)
 void write_binary_entry(std::ostream&amp; out, entry_t * entry)
 {
   write_binary_entry_base(out, entry);
-  write_binary_long(out, entry-&gt;_date);
-  write_binary_long(out, entry-&gt;_date_eff);
+  write_binary_number(out, entry-&gt;_date);
+  write_binary_number(out, entry-&gt;_date_eff);
   write_binary_string(out, entry-&gt;code);
   write_binary_string(out, entry-&gt;payee);
 }
@@ -1048,24 +1112,24 @@ void write_binary_commodity_base_extra(std::ostream&amp; out,
     for (history_map::const_iterator i = commodity-&gt;history-&gt;prices.begin();
 	 i != commodity-&gt;history-&gt;prices.end();
 	 i++) {
-      write_binary_long(out, (*i).first);
+      write_binary_number(out, (*i).first);
       write_binary_amount(out, (*i).second);
     }
-    write_binary_long(out, commodity-&gt;history-&gt;last_lookup);
+    write_binary_number(out, commodity-&gt;history-&gt;last_lookup);
   }
 
   if (commodity-&gt;smaller) {
-    write_binary_number&lt;unsigned char&gt;(out, 1);
+    write_binary_bool(out, true);
     write_binary_amount(out, *commodity-&gt;smaller);
   } else {
-    write_binary_number&lt;unsigned char&gt;(out, 0);
+    write_binary_bool(out, false);
   }
 
   if (commodity-&gt;larger) {
-    write_binary_number&lt;unsigned char&gt;(out, 1);
+    write_binary_bool(out, true);
     write_binary_amount(out, *commodity-&gt;larger);
   } else {
-    write_binary_number&lt;unsigned char&gt;(out, 0);
+    write_binary_bool(out, false);
   }
 }
 
@@ -1090,7 +1154,7 @@ void write_binary_commodity_annotated(std::ostream&amp; out,
 
   write_binary_long(out, ann_comm-&gt;base-&gt;ident);
   write_binary_amount(out, ann_comm-&gt;price);
-  write_binary_long(out, ann_comm-&gt;date);
+  write_binary_number(out, ann_comm-&gt;date);
   write_binary_string(out, ann_comm-&gt;tag);
 }
 
@@ -1132,13 +1196,13 @@ void write_binary_journal(std::ostream&amp; out, journal_t * journal)
   base_commodity_index = 
   commodity_index      = 0;
 
-  write_binary_number(out, binary_magic_number);
-  write_binary_number(out, format_version);
+  write_binary_number_nocheck(out, binary_magic_number);
+  write_binary_number_nocheck(out, format_version);
 
   // Write out the files that participated in this journal, so that
   // they can be checked for changes on reading.
 
-  if (journal-&gt;sources.size() == 0) {
+  if (journal-&gt;sources.empty()) {
     write_binary_number&lt;unsigned short&gt;(out, 0);
   } else {
     write_binary_number&lt;unsigned short&gt;(out, journal-&gt;sources.size());
@@ -1148,7 +1212,7 @@ void write_binary_journal(std::ostream&amp; out, journal_t * journal)
       write_binary_string(out, *i);
       struct stat info;
       stat((*i).c_str(), &amp;info);
-      write_binary_long(out, std::time_t(info.st_mtime));
+      write_binary_number(out, std::time_t(info.st_mtime));
     }
 
     // Write out the price database that relates to this data file, so
@@ -1165,10 +1229,10 @@ void write_binary_journal(std::ostream&amp; out, journal_t * journal)
   write_binary_account(out, journal-&gt;master);
 
   if (journal-&gt;basket) {
-    write_binary_number&lt;bool&gt;(out, true);
+    write_binary_bool(out, true);
     write_binary_long(out, journal-&gt;basket-&gt;ident);
   } else {
-    write_binary_number&lt;bool&gt;(out, false);
+    write_binary_bool(out, false);
   }
 
   // Write out the number of entries, transactions, and amounts
@@ -1178,10 +1242,11 @@ void write_binary_journal(std::ostream&amp; out, journal_t * journal)
   write_binary_long&lt;unsigned long&gt;(out, journal-&gt;period_entries.size());
 
   ostream_pos_type xacts_val = out.tellp();
-
   write_binary_number&lt;unsigned long&gt;(out, 0);
+
   ostream_pos_type bigints_val = out.tellp();
   write_binary_number&lt;unsigned long&gt;(out, 0);
+
   bigints_count = 0;
 
   // Write out the commodities
@@ -1202,7 +1267,7 @@ void write_binary_journal(std::ostream&amp; out, journal_t * journal)
        i != commodity_t::commodities.end();
        i++) {
     if (! (*i).second-&gt;annotated) {
-      write_binary_number&lt;char&gt;(out, 0);
+      write_binary_bool(out, false);
       write_binary_commodity(out, (*i).second);
     }
   }
@@ -1211,7 +1276,7 @@ void write_binary_journal(std::ostream&amp; out, journal_t * journal)
        i != commodity_t::commodities.end();
        i++) {
     if ((*i).second-&gt;annotated) {
-      write_binary_number&lt;char&gt;(out, 1);
+      write_binary_bool(out, true);
       write_binary_string(out, (*i).first); // the mapping key
       write_binary_commodity_annotated(out, (*i).second);
     }</diff>
      <filename>binary.cc</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,6 @@
 #include &quot;walk.h&quot;
 
 #include &lt;fstream&gt;
-#include &lt;ctime&gt;
 #include &lt;cstdlib&gt;
 #ifdef WIN32
 #include &lt;io.h&gt;
@@ -96,12 +95,14 @@ config_t::config_t()
   prices_format	       = &quot;%[%Y/%m/%d %H:%M:%S %Z]   %-10A %12t %12T\n&quot;;
   pricesdb_format      = &quot;P %[%Y/%m/%d %H:%M:%S] %A %t\n&quot;;
 
-  download_quotes    = false;
-  use_cache	     = false;
-  cache_dirty        = false;
-  debug_mode         = false;
-  verbose_mode       = false;
-  trace_mode         = false;
+  pricing_leeway       = 24 * 3600;
+
+  download_quotes      = false;
+  use_cache	       = false;
+  cache_dirty	       = false;
+  debug_mode	       = false;
+  verbose_mode	       = false;
+  trace_mode	       = false;
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -109,9 +110,7 @@ config_t::config_t()
 void trace(const std::string&amp; cat, const std::string&amp; str)
 {
   char buf[32];
-  std::time_t now = std::time(NULL);
-  std::strftime(buf, 31, &quot;%H:%M:%S&quot;, std::localtime(&amp;now));
-
+  std::strftime(buf, 31, &quot;%H:%M:%S&quot;, datetime_t::now.localtime());
   std::cerr &lt;&lt; buf &lt;&lt; &quot; &quot; &lt;&lt; cat &lt;&lt; &quot;: &quot; &lt;&lt; str &lt;&lt; std::endl;
 }
 </diff>
      <filename>config.cc</filename>
    </modified>
    <modified>
      <diff>@@ -31,9 +31,13 @@ class config_t
   std::string prices_format;
   std::string pricesdb_format;
 
+  std::string date_input_format;
+
   std::string account;
   std::string pager;
 
+  unsigned long pricing_leeway;
+
   bool download_quotes;
   bool use_cache;
   bool cache_dirty;</diff>
      <filename>config.h</filename>
    </modified>
    <modified>
      <diff>@@ -7,19 +7,12 @@
 #include &lt;ctime&gt;
 #include &lt;cctype&gt;
 
-std::time_t         now	      = std::time(NULL);
-int                 now_year  = std::localtime(&amp;now)-&gt;tm_year;
+date_t       date_t::now(std::time(NULL));
+int	     date_t::current_year = date_t::now.year();
+std::string  date_t::input_format;
+std::string  date_t::output_format = &quot;%Y/%m/%d&quot;;
 
-static std::time_t  base      = -1;
-static int	    base_year = -1;
-
-static const int    month_days[12] = {
-  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-char input_format[128];
-
-const char * formats[] = {
+const char * date_t::formats[] = {
   &quot;%Y/%m/%d&quot;,
   &quot;%m/%d&quot;,
   &quot;%Y.%m.%d&quot;,
@@ -34,29 +27,70 @@ const char * formats[] = {
   NULL
 };
 
-std::string datetime_t::date_format = &quot;%Y/%m/%d&quot;;
+datetime_t datetime_t::now(std::time(NULL));
+
+namespace {
+  static std::time_t base = -1;
+  static int base_year = -1;
+
+  static const int month_days[12] = {
+    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+  };
+
+  bool parse_date_mask(const char * date_str, struct std::tm * result);
+  bool parse_date(const char * date_str, std::time_t * result,
+		  const int year = -1);
+  bool quick_parse_date(const char * date_str, std::time_t * result);
+}
+
+date_t::date_t(const std::string&amp; _when)
+{
+  if (! quick_parse_date(_when.c_str(), &amp;when))
+    throw new date_error
+      (std::string(&quot;Invalid date string: &quot;) + _when);
+}
 
-std::time_t interval_t::first(const std::time_t moment) const
+datetime_t::datetime_t(const std::string&amp; _when)
 {
-  std::time_t quant = begin;
+  if (const char * p = std::strchr(_when.c_str(), ' ')) {
+    date_t date(std::string(_when, 0, p - _when.c_str()));
 
-  if (moment &amp;&amp; std::difftime(moment, quant) &gt; 0) {
+    struct std::tm moment = *std::localtime(&amp;date.when);
+    if (! strptime(++p, &quot;%H:%M:%S&quot;, &amp;moment))
+      throw new datetime_error
+	(std::string(&quot;Invalid date/time string: &quot;) + _when);
+
+    when = std::mktime(&amp;moment);
+  } else {
+    when = date_t(_when).when;
+  }
+}
+
+datetime_t interval_t::first(const datetime_t&amp; moment) const
+{
+  datetime_t quant(begin);
+
+  if (moment &amp;&amp; moment &gt; quant) {
     // Find an efficient starting point for the upcoming while loop.
     // We want a date early enough that the range will be correct, but
     // late enough that we don't spend hundreds of thousands of loops
     // skipping through time.
 
-    struct std::tm * desc = std::localtime(&amp;moment);
+    struct std::tm * desc = std::localtime(&amp;moment.when);
+
     if (years)
       desc-&gt;tm_mon = 0;
-    desc-&gt;tm_mday = 1;
-    desc-&gt;tm_hour = 0;
-    desc-&gt;tm_min  = 0;
-    desc-&gt;tm_sec  = 0;
+    desc-&gt;tm_mday  = 1;
+
+    desc-&gt;tm_hour  = 0;
+    desc-&gt;tm_min   = 0;
+    desc-&gt;tm_sec   = 0;
+    desc-&gt;tm_isdst = -1;
+
     quant = std::mktime(desc);
 
-    std::time_t temp;
-    while (std::difftime(moment, temp = increment(quant)) &gt;= 0) {
+    datetime_t temp;
+    while (moment &gt;= (temp = increment(quant))) {
       if (quant == temp)
 	break;
       quant = temp;
@@ -66,145 +100,134 @@ std::time_t interval_t::first(const std::time_t moment) const
   return quant;
 }
 
-std::time_t interval_t::increment(const std::time_t moment) const
+datetime_t interval_t::increment(const datetime_t&amp; moment) const
 {
-  std::time_t then = moment;
+  struct std::tm * desc = std::localtime(&amp;moment.when);
 
-  if (years || months) {
-    struct std::tm * desc = std::localtime(&amp;then);
+  if (years)
+    desc-&gt;tm_year += years;
+  if (months)
+    desc-&gt;tm_mon += months;
+  if (days)
+    desc-&gt;tm_mon += days;
 
-    if (years)
-      desc-&gt;tm_year += years;
+  desc-&gt;tm_hour += hours;
+  desc-&gt;tm_min  += minutes;
+  desc-&gt;tm_sec  += seconds;
 
-    if (months) {
-      desc-&gt;tm_mon += months;
+  desc-&gt;tm_isdst = -1;
 
-      if (desc-&gt;tm_mon &gt; 11) {
-	desc-&gt;tm_year++;
-	desc-&gt;tm_mon -= 12;
-      }
-      else if (desc-&gt;tm_mon &lt; 0) {
-	desc-&gt;tm_year--;
-	desc-&gt;tm_mon += 12;
-      }
-    }
-
-    desc-&gt;tm_hour  = 0;
-    desc-&gt;tm_min   = 0;
-    desc-&gt;tm_sec   = 0;
-    desc-&gt;tm_isdst = 0;
-
-    then = std::mktime(desc);
-  }
-
-  return then + seconds;
+  return std::mktime(desc);
 }
 
-static void parse_inclusion_specifier(const std::string&amp; word,
-				      std::time_t *	 begin,
-				      std::time_t *	 end)
-{
-  struct std::tm when;
+namespace {
+  void parse_inclusion_specifier(const std::string&amp; word,
+				 datetime_t * begin, datetime_t * end)
+  {
+    struct std::tm when;
 
-  if (! parse_date_mask(word.c_str(), &amp;when))
-    throw new datetime_error(std::string(&quot;Could not parse date mask: &quot;) + word);
+    if (! parse_date_mask(word.c_str(), &amp;when))
+      throw new datetime_error(std::string(&quot;Could not parse date mask: &quot;) + word);
 
-  when.tm_hour = 0;
-  when.tm_min  = 0;
-  when.tm_sec  = 0;
+    when.tm_hour	= 0;
+    when.tm_min	= 0;
+    when.tm_sec	= 0;
+    when.tm_isdst = -1;
 
-  bool saw_year = true;
-  bool saw_mon  = true;
-  bool saw_day  = true;
+    bool saw_year = true;
+    bool saw_mon  = true;
+    bool saw_day  = true;
 
-  if (when.tm_year == -1) {
-    when.tm_year = now_year;
-    saw_year = false;
-  }
-  if (when.tm_mon == -1) {
-    when.tm_mon = 0;
-    saw_mon = false;
-  } else {
-    saw_year = false;		// don't increment by year if month used
-  }
-  if (when.tm_mday == -1) {
-    when.tm_mday = 1;
-    saw_day = false;
-  } else {
-    saw_mon = false;		// don't increment by month if day used
-    saw_year = false;		// don't increment by year if day used
-  }
+    if (when.tm_year == -1) {
+      when.tm_year = date_t::current_year;
+      saw_year = false;
+    }
+    if (when.tm_mon == -1) {
+      when.tm_mon = 0;
+      saw_mon = false;
+    } else {
+      saw_year = false;		// don't increment by year if month used
+    }
+    if (when.tm_mday == -1) {
+      when.tm_mday = 1;
+      saw_day = false;
+    } else {
+      saw_mon = false;		// don't increment by month if day used
+      saw_year = false;		// don't increment by year if day used
+    }
 
-  if (begin) {
-    *begin = std::mktime(&amp;when);
-    if (end)
-      *end = interval_t(saw_day ? 86400 : 0, saw_mon ? 1 : 0,
-			saw_year ? 1 : 0).increment(*begin);
-  }
-  else if (end) {
-    *end = std::mktime(&amp;when);
+    if (begin) {
+      *begin = std::mktime(&amp;when);
+      if (end)
+	*end = interval_t(saw_day ? 86400 : 0, saw_mon ? 1 : 0,
+			  saw_year ? 1 : 0).increment(*begin);
+    }
+    else if (end) {
+      *end = std::mktime(&amp;when);
+    }
   }
-}
-
-static inline void read_lower_word(std::istream&amp; in, std::string&amp; word) {
-  in &gt;&gt; word;
-  for (int i = 0, l = word.length(); i &lt; l; i++)
-    word[i] = std::tolower(word[i]);
-}
 
-static void parse_date_words(std::istream&amp; in, std::string&amp; word,
-			     std::time_t * begin, std::time_t * end)
-{
-  std::string type;
-  bool	      mon_spec = false;
-  char	      buf[32];
-
-  if (word == &quot;this&quot; || word == &quot;last&quot; || word == &quot;next&quot;) {
-    type = word;
-    if (! in.eof())
-      read_lower_word(in, word);
-    else
-      word = &quot;month&quot;;
-  } else {
-    type = &quot;this&quot;;
+  inline void read_lower_word(std::istream&amp; in, std::string&amp; word) {
+    in &gt;&gt; word;
+    for (int i = 0, l = word.length(); i &lt; l; i++)
+      word[i] = std::tolower(word[i]);
   }
 
-  if (word == &quot;month&quot;) {
-    std::strftime(buf, 31, &quot;%B&quot;, std::localtime(&amp;now));
-    word = buf;
-    mon_spec = true;
-  }
-  else if (word == &quot;year&quot;) {
-    std::strftime(buf, 31, &quot;%Y&quot;, std::localtime(&amp;now));
-    word = buf;
-  }
+  void parse_date_words(std::istream&amp; in, std::string&amp; word,
+			datetime_t * begin, datetime_t * end)
+  {
+    std::string type;
 
-  parse_inclusion_specifier(word, begin, end);
+    bool mon_spec = false;
+    char buf[32];
 
-  if (type == &quot;last&quot;) {
-    if (mon_spec) {
-      if (begin)
-	*begin = interval_t(0, -1, 0).increment(*begin);
-      if (end)
-	*end   = interval_t(0, -1, 0).increment(*end);
+    if (word == &quot;this&quot; || word == &quot;last&quot; || word == &quot;next&quot;) {
+      type = word;
+      if (! in.eof())
+	read_lower_word(in, word);
+      else
+	word = &quot;month&quot;;
     } else {
-      if (begin)
-	*begin = interval_t(0, 0, -1).increment(*begin);
-      if (end)
-	*end   = interval_t(0, 0, -1).increment(*end);
+      type = &quot;this&quot;;
     }
-  }
-  else if (type == &quot;next&quot;) {
-    if (mon_spec) {
-      if (begin)
-	*begin = interval_t(0, 1, 0).increment(*begin);
-      if (end)
-	*end   = interval_t(0, 1, 0).increment(*end);
-    } else {
-      if (begin)
-	*begin = interval_t(0, 0, 1).increment(*begin);
-      if (end)
-	*end   = interval_t(0, 0, 1).increment(*end);
+
+    if (word == &quot;month&quot;) {
+      std::strftime(buf, 31, &quot;%B&quot;, datetime_t::now.localtime());
+      word = buf;
+      mon_spec = true;
+    }
+    else if (word == &quot;year&quot;) {
+      std::strftime(buf, 31, &quot;%Y&quot;, datetime_t::now.localtime());
+      word = buf;
+    }
+
+    parse_inclusion_specifier(word, begin, end);
+
+    if (type == &quot;last&quot;) {
+      if (mon_spec) {
+	if (begin)
+	  *begin = interval_t(0, -1, 0).increment(*begin);
+	if (end)
+	  *end   = interval_t(0, -1, 0).increment(*end);
+      } else {
+	if (begin)
+	  *begin = interval_t(0, 0, -1).increment(*begin);
+	if (end)
+	  *end   = interval_t(0, 0, -1).increment(*end);
+      }
+    }
+    else if (type == &quot;next&quot;) {
+      if (mon_spec) {
+	if (begin)
+	  *begin = interval_t(0, 1, 0).increment(*begin);
+	if (end)
+	  *end   = interval_t(0, 1, 0).increment(*end);
+      } else {
+	if (begin)
+	  *begin = interval_t(0, 0, 1).increment(*begin);
+	if (end)
+	  *end   = interval_t(0, 0, 1).increment(*end);
+      }
     }
   }
 }
@@ -221,9 +244,9 @@ void interval_t::parse(std::istream&amp; in)
 	int quantity = std::atol(word.c_str());
 	read_lower_word(in, word);
 	if (word == &quot;days&quot;)
-	  seconds = 86400 * quantity;
+	  days = quantity;
 	else if (word == &quot;weeks&quot;)
-	  seconds = 7 * 86400 * quantity;
+	  days = 7 * quantity;
 	else if (word == &quot;months&quot;)
 	  months = quantity;
 	else if (word == &quot;quarters&quot;)
@@ -232,9 +255,9 @@ void interval_t::parse(std::istream&amp; in)
 	  years = quantity;
       }
       else if (word == &quot;day&quot;)
-	seconds = 86400;
+	days = 1;
       else if (word == &quot;week&quot;)
-	seconds = 7 * 86400;
+	days = 7;
       else if (word == &quot;month&quot;)
 	months = 1;
       else if (word == &quot;quarter&quot;)
@@ -243,11 +266,11 @@ void interval_t::parse(std::istream&amp; in)
 	years = 1;
     }
     else if (word == &quot;daily&quot;)
-      seconds = 86400;
+      days = 1;
     else if (word == &quot;weekly&quot;)
-      seconds = 7 * 86400;
+      days = 7;
     else if (word == &quot;biweekly&quot;)
-      seconds = 14 * 86400;
+      days = 14;
     else if (word == &quot;monthly&quot;)
       months = 1;
     else if (word == &quot;bimonthly&quot;)
@@ -277,42 +300,49 @@ void interval_t::parse(std::istream&amp; in)
   }
 }
 
-bool parse_date_mask(const char * date_str, struct std::tm * result)
-{
-  for (const char ** f = formats; *f; f++) {
-    memset(result, INT_MAX, sizeof(struct std::tm));
-    if (strptime(date_str, *f, result))
-      return true;
+namespace {
+  bool parse_date_mask(const char * date_str, struct std::tm * result)
+  {
+    if (! date_t::input_format.empty()) {
+      std::memset(result, INT_MAX, sizeof(struct std::tm));
+      if (strptime(date_str, date_t::input_format.c_str(), result))
+	return true;
+    }
+    for (const char ** f = date_t::formats; *f; f++) {
+      std::memset(result, INT_MAX, sizeof(struct std::tm));
+      if (strptime(date_str, *f, result))
+	return true;
+    }
+    return false;
   }
-  return false;
-}
 
-bool parse_date(const char * date_str, std::time_t * result, const int year)
-{
-  struct std::tm when;
+  bool parse_date(const char * date_str, std::time_t * result, const int year)
+  {
+    struct std::tm when;
 
-  if (! parse_date_mask(date_str, &amp;when))
-    return false;
+    if (! parse_date_mask(date_str, &amp;when))
+      return false;
 
-  when.tm_hour = 0;
-  when.tm_min  = 0;
-  when.tm_sec  = 0;
+    when.tm_hour = 0;
+    when.tm_min  = 0;
+    when.tm_sec  = 0;
 
-  if (when.tm_year == -1)
-    when.tm_year = ((year == -1) ? now_year : (year - 1900));
+    if (when.tm_year == -1)
+      when.tm_year = ((year == -1) ? date_t::current_year : (year - 1900));
 
-  if (when.tm_mon == -1)
-    when.tm_mon = 0;
+    if (when.tm_mon == -1)
+      when.tm_mon = 0;
 
-  if (when.tm_mday == -1)
-    when.tm_mday = 1;
+    if (when.tm_mday == -1)
+      when.tm_mday = 1;
 
-  *result = std::mktime(&amp;when);
+    *result = std::mktime(&amp;when);
 
-  return true;
-}
+    return true;
+  }
 
-bool quick_parse_date(const char * date_str, std::time_t * result)
-{
-  return parse_date(date_str, result, now_year + 1900);
+  bool quick_parse_date(const char * date_str, std::time_t * result)
+  {
+    return parse_date(date_str, result, date_t::current_year + 1900);
+  }
 }</diff>
      <filename>datetime.cc</filename>
    </modified>
    <modified>
      <diff>@@ -6,130 +6,307 @@
 
 #include &quot;error.h&quot;
 
+class date_error : public error {
+ public:
+  date_error(const std::string&amp; reason) throw() : error(reason) {}
+  virtual ~date_error() throw() {}
+};
+
 struct interval_t;
+class  datetime_t;
 
-struct datetime_t
+class date_t
 {
+  date_t(const datetime_t&amp; _when);
+
+ protected:
   std::time_t when;
 
-  static std::string date_format;
+ public:
+  static date_t       now;
+  static const char * formats[];
+  static int	      current_year;
+  static std::string  input_format;
+  static std::string  output_format;
 
-  datetime_t(const std::time_t _when) : when(_when) {}
+  date_t() : when(0) {}
+  date_t(const date_t&amp; _when) : when(_when.when) {}
 
-  datetime_t&amp; operator+=(const long secs) {
-    when += secs;
-    return *this;
+  date_t(const std::time_t _when) : when(_when) {
+#if 0
+    struct std::tm * moment = std::localtime(&amp;_when);
+    moment-&gt;tm_hour = 0;
+    moment-&gt;tm_min  = 0;
+    moment-&gt;tm_sec  = 0;
+    when = std::mktime(moment);
+#endif
   }
-  datetime_t&amp; operator-=(const long secs) {
-    when -= secs;
+  date_t(const interval_t&amp; period);
+  date_t(const std::string&amp; _when);
+
+  virtual ~date_t() {}
+
+  date_t&amp; operator=(const date_t&amp; _when) {
+    when = _when.when;
     return *this;
   }
+  date_t&amp; operator=(const std::time_t _when) {
+    return *this = date_t(_when);
+  }
+  date_t&amp; operator=(const datetime_t&amp; _when) {
+    return *this = date_t(_when);
+  }
+  date_t&amp; operator=(const interval_t&amp; period) {
+    return *this = date_t(period);
+  }
+  date_t&amp; operator=(const std::string&amp; _when) {
+    return *this = date_t(_when);
+  }
+
+  date_t&amp; operator+=(const interval_t&amp; period);
+
+  long operator-=(const date_t&amp; date) {
+    return (when - date.when) / 86400;
+  }
 
-  datetime_t&amp; operator=(const interval_t&amp; period);
-  datetime_t&amp; operator+=(const interval_t&amp; period);
+  virtual date_t&amp; operator+=(const long days) {
+    // jww (2006-03-26): This is not accurate enough when DST is in effect!
+    assert(0);
+    when += days * 86400;
+    return *this;
+  }
+  virtual date_t&amp; operator-=(const long days) {
+    assert(0);
+    when -= days * 86400;
+    return *this;
+  }
 
-#define DEF_DATETIME_OP(OP)			\
-  bool operator OP(const datetime_t&amp; other) {	\
+#define DEF_DATE_OP(OP)				\
+  bool operator OP(const date_t&amp; other) const {	\
     return when OP other.when;			\
   }
 
-  DEF_DATETIME_OP(&lt;)
-  DEF_DATETIME_OP(&lt;=)
-  DEF_DATETIME_OP(&gt;)
-  DEF_DATETIME_OP(&gt;=)
-  DEF_DATETIME_OP(==)
-  DEF_DATETIME_OP(!=)
+  DEF_DATE_OP(&lt;)
+  DEF_DATE_OP(&lt;=)
+  DEF_DATE_OP(&gt;)
+  DEF_DATE_OP(&gt;=)
+  DEF_DATE_OP(==)
+  DEF_DATE_OP(!=)
 
   operator bool() const {
     return when != 0;
   }
-  operator long() const {
-    return (long)when;
+  operator std::time_t() const {
+    return when;
   }
-  operator double() const {
-    return (double)when;
+  operator std::string() const {
+    return to_string();
   }
 
+  std::string to_string(const std::string&amp; format = output_format) const {
+    char buf[64];
+    std::strftime(buf, 63, format.c_str(), localtime());
+    return buf;
+  }    
+
   int year() const {
-    struct std::tm * desc = std::localtime(&amp;when);
-    return desc-&gt;tm_year + 1900;
+    return localtime()-&gt;tm_year + 1900;
   }
   int month() const {
-    struct std::tm * desc = std::localtime(&amp;when);
-    return desc-&gt;tm_mon + 1;
+    return localtime()-&gt;tm_mon + 1;
   }
   int day() const {
-    struct std::tm * desc = std::localtime(&amp;when);
-    return desc-&gt;tm_mday;
+    return localtime()-&gt;tm_mday;
+  }
+  int wday() const {
+    return localtime()-&gt;tm_wday;
   }
+
+  std::tm * localtime() const {
+    return std::localtime(&amp;when);
+  }
+
+  void write(std::ostream&amp; out,
+	     const std::string&amp; format = output_format) const {
+    out &lt;&lt; to_string(format);
+  }    
+
+  friend class datetime_t;
+  friend struct interval_t;
 };
 
-inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, const datetime_t&amp; moment) {
-  char buf[32];
-  std::strftime(buf, 31, datetime_t::date_format.c_str(),
-		std::localtime(&amp;moment.when));
-  out &lt;&lt; buf;
+inline long operator-(const date_t&amp; left, const date_t&amp; right) {
+  date_t temp(left);
+  temp -= right;
+  return temp;
+}
+
+inline date_t operator+(const date_t&amp; left, const long days) {
+  date_t temp(left);
+  temp += days;
+  return temp;
+}
+
+inline date_t operator-(const date_t&amp; left, const long days) {
+  date_t temp(left);
+  temp -= days;
+  return temp;
 }
 
+inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, const date_t&amp; moment) {
+  moment.write(out);
+}
+
+class datetime_error : public error {
+ public:
+  datetime_error(const std::string&amp; reason) throw() : error(reason) {}
+  virtual ~datetime_error() throw() {}
+};
+
+class datetime_t : public date_t
+{
+ public:
+  static datetime_t now;
+
+  datetime_t() : date_t() {}
+  datetime_t(const datetime_t&amp; _when) : date_t(_when.when) {}
+  datetime_t(const date_t&amp; _when) : date_t(_when) {}
+
+  datetime_t(const std::time_t _when) : date_t(_when) {}
+  datetime_t(const std::string&amp; _when);
+
+  datetime_t&amp; operator=(const datetime_t&amp; _when) {
+    when = _when.when;
+    return *this;
+  }
+  datetime_t&amp; operator=(const date_t&amp; _when) {
+    when = _when.when;
+    return *this;
+  }
+  datetime_t&amp; operator=(const std::time_t _when) {
+    return *this = datetime_t(_when);
+  }
+  datetime_t&amp; operator=(const std::string&amp; _when) {
+    return *this = datetime_t(_when);
+  }
+
+  long operator-=(const datetime_t&amp; date) {
+    return when - date.when;
+  }
+
+  virtual datetime_t&amp; operator+=(const long secs) {
+    when += secs;
+    return *this;
+  }
+  virtual datetime_t&amp; operator-=(const long secs) {
+    when -= secs;
+    return *this;
+  }
+
+#define DEF_DATETIME_OP(OP)				\
+  bool operator OP(const datetime_t&amp; other) const {	\
+    return when OP other.when;				\
+  }
+
+  DEF_DATETIME_OP(&lt;)
+  DEF_DATETIME_OP(&lt;=)
+  DEF_DATETIME_OP(&gt;)
+  DEF_DATETIME_OP(&gt;=)
+  DEF_DATETIME_OP(==)
+  DEF_DATETIME_OP(!=)
+
+  int hour() const {
+    return localtime()-&gt;tm_hour;
+  }
+  int min() const {
+    return localtime()-&gt;tm_min;
+  }
+  int sec() const {
+    return localtime()-&gt;tm_sec;
+  }
+};
+
 inline long operator-(const datetime_t&amp; left, const datetime_t&amp; right) {
-  return (long)left.when - (long)right.when;
+  datetime_t temp(left);
+  temp -= right;
+  return temp;
+}
+
+inline datetime_t operator+(const datetime_t&amp; left, const long seconds) {
+  datetime_t temp(left);
+  temp += seconds;
+  return temp;
+}
+
+inline datetime_t operator-(const datetime_t&amp; left, const long seconds) {
+  datetime_t temp(left);
+  temp -= seconds;
+  return temp;
+}
+
+inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,
+				const datetime_t&amp; moment) {
+  char buf[64];
+  std::strftime(buf, 63, (date_t::output_format + &quot; %H:%M:%S&quot;).c_str(),
+		moment.localtime());
+  out &lt;&lt; buf;
 }
 
 struct interval_t
 {
-  unsigned int years;
-  unsigned int months;
-  unsigned int seconds;
-  std::time_t  begin;
-  std::time_t  end;
+  unsigned short years;
+  unsigned short months;
+  unsigned short days;
+  unsigned short hours;
+  unsigned short minutes;
+  unsigned short seconds;
+
+  datetime_t begin;
+  datetime_t end;
+
+  interval_t(int _days = 0, int _months = 0, int _years = 0,
+	     const date_t&amp; _begin = date_t(),
+	     const date_t&amp; _end   = date_t())
+    : years(_years), months(_months), days(_days),
+      hours(0), minutes(0), seconds(0),
+      begin(_begin), end(_end) {}
 
-  interval_t(int _seconds = 0, int _months = 0, int _years = 0,
-	     std::time_t _begin = 0, std::time_t _end = 0)
-    : years(_years), months(_months), seconds(_seconds),
-      begin(_begin), end(_end) {
-  }
   interval_t(const std::string&amp; desc)
-    : years(0), months(0), seconds(0), begin(0), end(0) {
+    : years(0), months(0), days(0),
+      hours(0), minutes(0), seconds(0) {
     std::istringstream stream(desc);
     parse(stream);
   }
 
   operator bool() const {
-    return seconds &gt; 0 || months &gt; 0 || years &gt; 0;
+    return (years &gt; 0 || months &gt; 0  || days &gt; 0 ||
+	    hours &gt; 0 || minutes &gt; 0 || seconds &gt; 0);
   }
 
-  void start(const std::time_t moment) {
+  void start(const datetime_t&amp; moment) {
     begin = first(moment);
   }
-  std::time_t first(const std::time_t moment = 0) const;
-  std::time_t increment(const std::time_t) const;
+  datetime_t first(const datetime_t&amp; moment = datetime_t()) const;
+  datetime_t increment(const datetime_t&amp;) const;
 
   void parse(std::istream&amp; in);
 };
 
-inline datetime_t&amp; datetime_t::operator=(const interval_t&amp; period) {
-  when = period.first();
-  return *this;
+inline date_t::date_t(const interval_t&amp; period) {
+  when = period.first().when;
 }
-inline datetime_t&amp; datetime_t::operator+=(const interval_t&amp; period) {
-  when = period.increment(when);
-  return *this;
-}
-
-extern std::time_t  now;
-extern int	    now_year;
-extern char         input_format[128];
-extern const char * formats[];
 
-bool parse_date_mask(const char * date_str, struct std::tm * result);
-bool parse_date(const char * date_str, std::time_t * result,
-		const int year = -1);
-bool quick_parse_date(const char * date_str, std::time_t * result);
+inline date_t&amp; date_t::operator+=(const interval_t&amp; period) {
+  return *this = period.increment(*this);
+}
 
-class datetime_error : public error {
- public:
-  datetime_error(const std::string&amp; reason) throw() : error(reason) {}
-  virtual ~datetime_error() throw() {}
-};
+inline date_t::date_t(const datetime_t&amp; _when) {
+  assert(0);
+  struct std::tm * moment = _when.localtime();
+  moment-&gt;tm_hour = 0;
+  moment-&gt;tm_min  = 0;
+  moment-&gt;tm_sec  = 0;
+  when = std::mktime(moment);
+}
 
 #endif // _DATETIME_H</diff>
      <filename>datetime.h</filename>
    </modified>
    <modified>
      <diff>@@ -62,7 +62,8 @@ void debug_assert(const std::string&amp; reason,
 #include &lt;new&gt;
 #include &lt;iostream&gt;
 #include &lt;cstdlib&gt;
-#include &lt;ctime&gt;
+
+#include &quot;datetime.h&quot;
 
 #define DEBUG_ENABLED
 
@@ -85,10 +86,8 @@ bool _debug_active(const char * const cls);
   }
 #define DEBUG_PRINT_(x) DEBUG_PRINT(_debug_cls, x)
 
-#define DEBUG_PRINT_TIME(cls, x) {				\
-  char buf[32];							\
-  std::strftime(buf, 31, &quot;%Y/%m/%d:%H&quot;, std::localtime(&amp;x));	\
-  DEBUG_PRINT(cls, #x &lt;&lt; &quot; is &quot; &lt;&lt; buf);			\
+#define DEBUG_PRINT_TIME(cls, x) {		\
+  DEBUG_PRINT(cls, #x &lt;&lt; &quot; is &quot; &lt;&lt; x);		\
 }
 
 #define DEBUG_PRINT_TIME_(x) DEBUG_PRINT_TIME(_debug_cls, x)</diff>
      <filename>debug.h</filename>
    </modified>
    <modified>
      <diff>@@ -16,10 +16,8 @@ entry_t * derive_new_entry(journal_t&amp; journal,
 
   entry_t * matching = NULL;
 
-  if (! parse_date((*i).c_str(), &amp;added-&gt;_date))
-    throw new error(&quot;Bad date passed to 'entry'&quot;);
-
-  if (++i == end)
+  added-&gt;_date = *i++;
+  if (i == end)
     throw new error(&quot;Too few arguments to 'entry'&quot;);
 
   mask_t regexp(*i++);</diff>
      <filename>derive.cc</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,6 @@
 #include &quot;util.h&quot;
 
 #include &lt;cstdlib&gt;
-#include &lt;ctime&gt;
 
 namespace ledger {
 
@@ -208,11 +207,11 @@ element_t * format_t::parse_elements(const std::string&amp; fmt)
 
     case 'd':
       current-&gt;type  = element_t::COMPLETE_DATE_STRING;
-      current-&gt;chars = datetime_t::date_format;
+      current-&gt;chars = datetime_t::output_format;
       break;
     case 'D':
       current-&gt;type  = element_t::DATE_STRING;
-      current-&gt;chars = datetime_t::date_format;
+      current-&gt;chars = datetime_t::output_format;
       break;
 
     case 'S': current-&gt;type = element_t::SOURCE; break;
@@ -536,21 +535,21 @@ void format_t::format(std::ostream&amp; out_str, const details_t&amp; details) const
       break;
 
     case element_t::DATE_STRING: {
-      std::time_t date = 0;
+      datetime_t date;
       if (details.xact)
 	date = details.xact-&gt;date();
       else if (details.entry)
 	date = details.entry-&gt;date();
 
       char buf[256];
-      std::strftime(buf, 255, elem-&gt;chars.c_str(), std::localtime(&amp;date));
+      std::strftime(buf, 255, elem-&gt;chars.c_str(), date.localtime());
       out &lt;&lt; (elem-&gt;max_width == 0 ? buf : truncated(buf, elem-&gt;max_width));
       break;
     }
 
     case element_t::COMPLETE_DATE_STRING: {
-      std::time_t actual_date = 0;
-      std::time_t effective_date = 0;
+      datetime_t actual_date;
+      datetime_t effective_date;
       if (details.xact) {
 	actual_date    = details.xact-&gt;actual_date();
 	effective_date = details.xact-&gt;effective_date();
@@ -561,14 +560,13 @@ void format_t::format(std::ostream&amp; out_str, const details_t&amp; details) const
       }
 
       char abuf[256];
-      std::strftime(abuf, 255, elem-&gt;chars.c_str(),
-		    std::localtime(&amp;actual_date));
+      std::strftime(abuf, 255, elem-&gt;chars.c_str(), actual_date.localtime());
 
-      if (effective_date != 0 &amp;&amp; effective_date != actual_date) {
+      if (effective_date &amp;&amp; effective_date != actual_date) {
 	char buf[512];
 	char ebuf[256];
 	std::strftime(ebuf, 255, elem-&gt;chars.c_str(),
-		    std::localtime(&amp;effective_date));
+		      effective_date.localtime());
 
 	std::strcpy(buf, abuf);
 	std::strcat(buf, &quot;=&quot;);
@@ -892,7 +890,7 @@ format_equity::format_equity(std::ostream&amp;      _output_stream,
 
   entry_t header_entry;
   header_entry.payee = &quot;Opening Balances&quot;;
-  header_entry._date = now;
+  header_entry._date = datetime_t::now;
   first_line_format.format(output_stream, details_t(header_entry));
 }
 </diff>
      <filename>format.cc</filename>
    </modified>
    <modified>
      <diff>@@ -292,12 +292,9 @@ static void dataHandler(void *userData, const char *s, int len)
     curr_entry-&gt;code = std::string(s, len);
     break;
 
-  case ENTRY_DATE: {
-    struct tm when;
-    strptime(std::string(s, len).c_str(), &quot;%Y-%m-%d %H:%M:%S %z&quot;, &amp;when);
-    curr_entry-&gt;_date = std::mktime(&amp;when);
+  case ENTRY_DATE:
+    curr_entry-&gt;_date = std::string(s, len);
     break;
-  }
 
   case ENTRY_DESC:
     curr_entry-&gt;payee = std::string(s, len);
@@ -375,6 +372,10 @@ unsigned int gnucash_parser_t::parse(std::istream&amp;	 in,
 {
   char buf[BUFSIZ];
 
+  // This is the date format used by Gnucash, so override whatever the
+  // user specified.
+  date_t::input_format = &quot;%Y-%m-%d %H:%M:%S %z&quot;;
+
   count		 = 0;
   action	 = NO_ACTION;
   curr_journal	 = journal;</diff>
      <filename>gnucash.cc</filename>
    </modified>
    <modified>
      <diff>@@ -19,16 +19,16 @@ transaction_t::~transaction_t()
   if (cost) delete cost;
 }
 
-std::time_t transaction_t::actual_date() const
+datetime_t transaction_t::actual_date() const
 {
-  if (_date == 0 &amp;&amp; entry)
+  if (! _date &amp;&amp; entry)
     return entry-&gt;actual_date();
   return _date;
 }
 
-std::time_t transaction_t::effective_date() const
+datetime_t transaction_t::effective_date() const
 {
-  if (_date_eff == 0 &amp;&amp; entry)
+  if (! _date_eff &amp;&amp; entry)
     return entry-&gt;effective_date();
   return _date_eff;
 }
@@ -176,9 +176,10 @@ bool entry_base_t::finalize()
 
       if ((*x)-&gt;amount.commodity() &amp;&amp;
 	  ! (*x)-&gt;amount.commodity().annotated)
-	(*x)-&gt;amount.annotate_commodity(abs(per_unit_cost),
-					entry ? entry-&gt;actual_date() : 0,
-					entry ? entry-&gt;code : &quot;&quot;);
+	(*x)-&gt;amount.annotate_commodity
+	  (abs(per_unit_cost),
+	   entry ? entry-&gt;actual_date() : datetime_t(),
+	   entry ? entry-&gt;code : &quot;&quot;);
 
       (*x)-&gt;cost = new amount_t(- (per_unit_cost * (*x)-&gt;amount));
       balance += *(*x)-&gt;cost;</diff>
      <filename>journal.cc</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,6 @@
 #include &lt;map&gt;
 #include &lt;list&gt;
 #include &lt;string&gt;
-#include &lt;ctime&gt;
 #include &lt;iostream&gt;
 
 #include &quot;amount.h&quot;
@@ -34,8 +33,8 @@ class transaction_t
   enum state_t { UNCLEARED, CLEARED, PENDING };
 
   entry_t *	   entry;
-  std::time_t	   _date;
-  std::time_t	   _date_eff;
+  datetime_t	   _date;
+  datetime_t	   _date_eff;
   account_t *	   account;
   amount_t	   amount;
   value_expr       amount_expr;
@@ -53,8 +52,8 @@ class transaction_t
   static bool    use_effective_date;
 
   transaction_t(account_t * _account = NULL)
-    : entry(NULL), _date(0), _date_eff(0), account(_account),
-      cost(NULL), state(UNCLEARED), flags(TRANSACTION_NORMAL),
+    : entry(NULL), account(_account), cost(NULL),
+      state(UNCLEARED), flags(TRANSACTION_NORMAL),
       beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
     DEBUG_PRINT(&quot;ledger.memory.ctors&quot;, &quot;ctor transaction_t&quot;);
   }
@@ -62,24 +61,24 @@ class transaction_t
 		const amount_t&amp;    _amount,
 		unsigned int	   _flags = TRANSACTION_NORMAL,
 		const std::string&amp; _note  = &quot;&quot;)
-    : entry(NULL), _date(0), _date_eff(0), account(_account),
-      amount(_amount), cost(NULL), state(UNCLEARED), flags(_flags),
+    : entry(NULL), account(_account), amount(_amount), cost(NULL),
+      state(UNCLEARED), flags(_flags),
       note(_note), beg_pos(0), beg_line(0), end_pos(0), end_line(0),
       data(NULL) {
     DEBUG_PRINT(&quot;ledger.memory.ctors&quot;, &quot;ctor transaction_t&quot;);
   }
   transaction_t(const transaction_t&amp; xact)
-    : entry(xact.entry), _date(0), _date_eff(0), account(xact.account),
-      amount(xact.amount), cost(xact.cost ? new amount_t(*xact.cost) : NULL),
+    : entry(xact.entry), account(xact.account), amount(xact.amount),
+      cost(xact.cost ? new amount_t(*xact.cost) : NULL),
       state(xact.state), flags(xact.flags), note(xact.note),
       beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
     DEBUG_PRINT(&quot;ledger.memory.ctors&quot;, &quot;ctor transaction_t&quot;);
   }
   ~transaction_t();
 
-  std::time_t actual_date() const;
-  std::time_t effective_date() const;
-  std::time_t date() const {
+  datetime_t actual_date() const;
+  datetime_t effective_date() const;
+  datetime_t date() const {
     if (use_effective_date)
       return effective_date();
     else
@@ -162,12 +161,12 @@ class entry_base_t
 class entry_t : public entry_base_t
 {
  public:
-  std::time_t _date;
-  std::time_t _date_eff;
+  datetime_t  _date;
+  datetime_t  _date_eff;
   std::string code;
   std::string payee;
 
-  entry_t() : _date(0), _date_eff(0) {
+  entry_t() {
     DEBUG_PRINT(&quot;ledger.memory.ctors&quot;, &quot;ctor entry_t&quot;);
   }
   entry_t(const entry_t&amp; e);
@@ -176,15 +175,15 @@ class entry_t : public entry_base_t
     DEBUG_PRINT(&quot;ledger.memory.dtors&quot;, &quot;dtor entry_t&quot;);
   }
 
-  std::time_t actual_date() const {
+  datetime_t actual_date() const {
     return _date;
   }
-  std::time_t effective_date() const {
-    if (_date_eff == 0)
+  datetime_t effective_date() const {
+    if (! _date_eff)
       return _date;
     return _date_eff;
   }
-  std::time_t date() const {
+  datetime_t date() const {
     if (transaction_t::use_effective_date)
       return effective_date();
     else</diff>
      <filename>journal.h</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,6 @@
 #include &lt;cstdio&gt;
 #include &lt;cstdlib&gt;
 #include &lt;cstring&gt;
-#include &lt;ctime&gt;
 
 #include &quot;acconf.h&quot;
 
@@ -28,7 +27,7 @@ int parse_and_report(config_t&amp; config, report_t&amp; report,
 {
   // Configure the terminus for value expressions
 
-  ledger::terminus = now;
+  ledger::terminus = datetime_t::now;
 
   // Parse command-line arguments, and those set in the environment
 
@@ -49,7 +48,8 @@ int parse_and_report(config_t&amp; config, report_t&amp; report,
 
   TRACE(main, &quot;Processing options and environment variables&quot;);
 
-  process_environment(ledger::config_options, envp, &quot;LEDGER_&quot;);
+  process_environment(ledger::config_options,
+		      const_cast&lt;const char **&gt;(envp), &quot;LEDGER_&quot;);
 
 #if 1
   // These are here for backwards compatability, but are deprecated.
@@ -175,11 +175,10 @@ int parse_and_report(config_t&amp; config, report_t&amp; report,
 
   // If downloading is to be supported, configure the updater
 
-  // jww (2006-03-23): Should the pricing_leeway be in config_t?
-  // Should download_quotes be in report_t?
   if (! commodity_base_t::updater &amp;&amp; config.download_quotes)
     commodity_base_t::updater =
-      new quotes_by_script(config.price_db, report.pricing_leeway, config.cache_dirty);
+      new quotes_by_script(config.price_db, config.pricing_leeway,
+			   config.cache_dirty);
 
   std::auto_ptr&lt;entry_t&gt; new_entry;
   if (command == &quot;e&quot;) {
@@ -325,13 +324,8 @@ appending the output of this command to your Ledger file if you so choose.&quot;
     formatter = new format_entries(*out, *format);
   else if (command == &quot;x&quot;)
     formatter = new format_emacs_transactions(*out);
-#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
   else if (command == &quot;X&quot;)
     formatter = new format_xml_entries(*out, report.show_totals);
-#else
-  else if (command == &quot;X&quot;)
-    throw new error(&quot;XML support was not compiled into this copy of Ledger&quot;);
-#endif
   else
     formatter = new format_transactions(*out, *format);
 </diff>
      <filename>main.cc</filename>
    </modified>
    <modified>
      <diff>@@ -93,7 +93,7 @@ void process_arguments(option_t * options, int argc, char ** argv,
       if ((*i)[2] == '\0')
 	break;
 
-      char * name  = *i + 2;
+      char * name = *i + 2;
       if (char * p = std::strchr(name, '=')) {
 	*p++ = '\0';
 	value = p;
@@ -132,17 +132,17 @@ void process_arguments(option_t * options, int argc, char ** argv,
   }
 }
 
-void process_environment(option_t * options, char ** envp,
+void process_environment(option_t * options, const char ** envp,
 			 const std::string&amp; tag)
 {
   const char * tag_p   = tag.c_str();
   unsigned int tag_len = tag.length();
 
-  for (char ** p = envp; *p; p++)
+  for (const char ** p = envp; *p; p++)
     if (! tag_p || std::strncmp(*p, tag_p, tag_len) == 0) {
       char   buf[128];
       char * r = buf;
-      char * q;
+      const char * q;
       for (q = *p + tag_len;
 	   *q &amp;&amp; *q != '=' &amp;&amp; r - buf &lt; 128;
 	   q++)
@@ -459,32 +459,28 @@ OPT_BEGIN(effective, &quot;&quot;) {
 OPT_BEGIN(begin, &quot;b:&quot;) {
   char buf[128];
   interval_t interval(optarg);
-  if (interval.begin)
-    std::strftime(buf, 127, formats[0], std::localtime(&amp;interval.begin));
-  else
+  if (! interval.begin)
     throw new error(std::string(&quot;Could not determine beginning of period '&quot;) +
 		    optarg + &quot;'&quot;);
 
   if (! report-&gt;predicate.empty())
     report-&gt;predicate += &quot;&amp;&quot;;
   report-&gt;predicate += &quot;d&gt;=[&quot;;
-  report-&gt;predicate += buf;
+  report-&gt;predicate += interval.begin.to_string();
   report-&gt;predicate += &quot;]&quot;;
 } OPT_END(begin);
 
 OPT_BEGIN(end, &quot;e:&quot;) {
   char buf[128];
   interval_t interval(optarg);
-  if (interval.end)
-    std::strftime(buf, 127, formats[0], std::localtime(&amp;interval.end));
-  else
+  if (! interval.end)
     throw new error(std::string(&quot;Could not determine end of period '&quot;) +
 		    optarg + &quot;'&quot;);
 
   if (! report-&gt;predicate.empty())
     report-&gt;predicate += &quot;&amp;&quot;;
   report-&gt;predicate += &quot;d&lt;[&quot;;
-  report-&gt;predicate += buf;
+  report-&gt;predicate += interval.end.to_string();
   report-&gt;predicate += &quot;]&quot;;
 
   terminus = interval.end;
@@ -547,12 +543,11 @@ OPT_BEGIN(format, &quot;F:&quot;) {
 } OPT_END(format);
 
 OPT_BEGIN(date_format, &quot;y:&quot;) {
-  report-&gt;date_format = optarg;
+  report-&gt;date_output_format = optarg;
 } OPT_END(date_format);
 
 OPT_BEGIN(input_date_format, &quot;:&quot;) {
-  std::strcpy(input_format, optarg);
-  formats[0] = input_format;
+  config-&gt;date_input_format = optarg;
 } OPT_END(input_date_format);
 
 OPT_BEGIN(balance_format, &quot;:&quot;) {
@@ -684,26 +679,21 @@ OPT_BEGIN(period, &quot;p:&quot;) {
   // modify the calculation predicate (via the --begin and --end
   // options) to take this into account.
 
-  char buf[128];
   interval_t interval(report-&gt;report_period);
 
   if (interval.begin) {
-    std::strftime(buf, 127, formats[0], std::localtime(&amp;interval.begin));
-
     if (! report-&gt;predicate.empty())
       report-&gt;predicate += &quot;&amp;&quot;;
     report-&gt;predicate += &quot;d&gt;=[&quot;;
-    report-&gt;predicate += buf;
+    report-&gt;predicate += interval.begin.to_string();
     report-&gt;predicate += &quot;]&quot;;
   }
 
   if (interval.end) {
-    std::strftime(buf, 127, formats[0], std::localtime(&amp;interval.end));
-
     if (! report-&gt;predicate.empty())
       report-&gt;predicate += &quot;&amp;&quot;;
     report-&gt;predicate += &quot;d&lt;[&quot;;
-    report-&gt;predicate += buf;
+    report-&gt;predicate += interval.end.to_string();
     report-&gt;predicate += &quot;]&quot;;
 
     terminus = interval.end;
@@ -731,6 +721,13 @@ OPT_BEGIN(monthly, &quot;M&quot;) {
     report-&gt;report_period = std::string(&quot;monthly &quot;) + report-&gt;report_period;
 } OPT_END(monthly);
 
+OPT_BEGIN(quarterly, &quot;&quot;) {
+  if (report-&gt;report_period.empty())
+    report-&gt;report_period = &quot;quarterly&quot;;
+  else
+    report-&gt;report_period = std::string(&quot;quarterly &quot;) + report-&gt;report_period;
+} OPT_END(quarterly);
+
 OPT_BEGIN(yearly, &quot;Y&quot;) {
   if (report-&gt;report_period.empty())
     report-&gt;report_period = &quot;yearly&quot;;
@@ -841,7 +838,7 @@ OPT_BEGIN(price_db, &quot;:&quot;) {
 } OPT_END(price_db);
 
 OPT_BEGIN(price_exp, &quot;Z:&quot;) {
-  report-&gt;pricing_leeway = std::atol(optarg) * 60;
+  config-&gt;pricing_leeway = std::atol(optarg) * 60;
 } OPT_END(price_exp);
 
 OPT_BEGIN(download, &quot;Q&quot;) {
@@ -886,8 +883,8 @@ namespace {
     amount_t price(equals + 1);
 
     if (commodity_t * commodity = commodity_t::find_or_create(symbol)) {
-      commodity-&gt;add_price(now, price);
-      commodity-&gt;history()-&gt;bogus_time = now;
+      commodity-&gt;add_price(datetime_t::now, price);
+      commodity-&gt;history()-&gt;bogus_time = datetime_t::now;
     }
   }
 }
@@ -1012,6 +1009,7 @@ option_t config_options[CONFIG_OPTIONS_SIZE] = {
   { &quot;prices-format&quot;, '\0', true, opt_prices_format, false },
   { &quot;print-format&quot;, '\0', true, opt_print_format, false },
   { &quot;quantity&quot;, 'O', false, opt_quantity, false },
+  { &quot;quarterly&quot;, '\0', false, opt_quarterly, false },
   { &quot;real&quot;, 'R', false, opt_real, false },
   { &quot;reconcile&quot;, '\0', true, opt_reconcile, false },
   { &quot;reconcile-date&quot;, '\0', true, opt_reconcile_date, false },</diff>
      <filename>option.cc</filename>
    </modified>
    <modified>
      <diff>@@ -27,7 +27,7 @@ bool process_option(option_t * options, const std::string&amp; opt,
 		    const char * arg = NULL);
 void process_arguments(option_t * options, int argc, char ** argv,
 		       const bool anywhere, std::list&lt;std::string&gt;&amp; args);
-void process_environment(option_t * options, char ** envp,
+void process_environment(option_t * options, const char ** envp,
 			 const std::string&amp; tag);
 
 namespace ledger {
@@ -38,7 +38,7 @@ class report_t;
 extern config_t * config;
 extern report_t * report;
 
-#define CONFIG_OPTIONS_SIZE 94
+#define CONFIG_OPTIONS_SIZE 95
 extern option_t config_options[CONFIG_OPTIONS_SIZE];
 
 void option_help(std::ostream&amp; out);</diff>
      <filename>option.h</filename>
    </modified>
    <modified>
      <diff>@@ -104,8 +104,7 @@ unsigned int qif_parser_t::parse(std::istream&amp;	     in,
     case 'D':
       SET_BEG_POS_AND_LINE();
       get_line(in);
-      if (! parse_date(line, &amp;entry-&gt;_date))
-	throw new parse_error(&quot;Failed to parse date&quot;);
+      entry-&gt;_date = line;
       break;
 
     case 'T':</diff>
      <filename>qif.cc</filename>
    </modified>
    <modified>
      <diff>@@ -10,15 +10,15 @@
 namespace ledger {
 
 void quotes_by_script::operator()(commodity_base_t&amp; commodity,
-				  const std::time_t moment,
-				  const std::time_t date,
-				  const std::time_t last,
+				  const datetime_t&amp; moment,
+				  const datetime_t&amp; date,
+				  const datetime_t&amp; last,
 				  amount_t&amp;	    price)
 {
   DEBUG_CLASS(&quot;ledger.quotes.download&quot;);
 
   DEBUG_PRINT_(&quot;commodity: &quot; &lt;&lt; commodity.symbol);
-  DEBUG_PRINT_TIME_(now);
+  DEBUG_PRINT_TIME_(datetime_t::now);
   DEBUG_PRINT_TIME_(moment);
   DEBUG_PRINT_TIME_(date);
   DEBUG_PRINT_TIME_(last);
@@ -27,10 +27,9 @@ void quotes_by_script::operator()(commodity_base_t&amp; commodity,
   DEBUG_PRINT_(&quot;pricing_leeway is &quot; &lt;&lt; pricing_leeway);
 
   if ((commodity.history &amp;&amp;
-       std::difftime(now, commodity.history-&gt;last_lookup) &lt; pricing_leeway) ||
-      std::difftime(now, last) &lt; pricing_leeway ||
-      (price &amp;&amp; std::difftime(moment, date) &gt; 0 &amp;&amp;
-       std::difftime(moment, date) &lt;= pricing_leeway))
+       (datetime_t::now - commodity.history-&gt;last_lookup) &lt; pricing_leeway) ||
+      (datetime_t::now - last) &lt; pricing_leeway ||
+      (price &amp;&amp; moment &gt; date &amp;&amp; (moment - date) &lt;= pricing_leeway))
     return;
 
   using namespace std;
@@ -59,20 +58,19 @@ void quotes_by_script::operator()(commodity_base_t&amp; commodity,
     DEBUG_PRINT_(&quot;downloaded quote: &quot; &lt;&lt; buf);
 
     price.parse(buf);
-    commodity.add_price(now, price);
+    commodity.add_price(datetime_t::now, price);
 
-    commodity.history-&gt;last_lookup = now;
+    commodity.history-&gt;last_lookup = datetime_t::now;
     cache_dirty = true;
 
     if (price &amp;&amp; ! price_db.empty()) {
-      strftime(buf, 127, &quot;%Y/%m/%d %H:%M:%S&quot;, localtime(&amp;now));
 #if defined(__GNUG__) &amp;&amp; __GNUG__ &lt; 3
       ofstream database(price_db.c_str(), ios::out | ios::app);
 #else
       ofstream database(price_db.c_str(), ios_base::out | ios_base::app);
 #endif
-      database &lt;&lt; &quot;P &quot; &lt;&lt; buf &lt;&lt; &quot; &quot; &lt;&lt; commodity.symbol
-	       &lt;&lt; &quot; &quot; &lt;&lt; price &lt;&lt; endl;
+      database &lt;&lt; &quot;P &quot; &lt;&lt; datetime_t::now.to_string(&quot;%Y/%m/%d %H:%M:%S&quot;)
+	       &lt;&lt; &quot; &quot; &lt;&lt; commodity.symbol &lt;&lt; &quot; &quot; &lt;&lt; price &lt;&lt; endl;
     }
   } else {
     throw new error(std::string(&quot;Failed to download price for '&quot;) +</diff>
      <filename>quotes.cc</filename>
    </modified>
    <modified>
      <diff>@@ -19,9 +19,9 @@ class quotes_by_script : public commodity_base_t::updater_t
       cache_dirty(_cache_dirty) {}
 
   virtual void operator()(commodity_base_t&amp; commodity,
-			  const std::time_t moment,
-			  const std::time_t date,
-			  const std::time_t last,
+			  const datetime_t&amp; moment,
+			  const datetime_t&amp; date,
+			  const datetime_t&amp; last,
 			  amount_t&amp;	    price);
 };
 </diff>
      <filename>quotes.h</filename>
    </modified>
    <modified>
      <diff>@@ -44,7 +44,7 @@ void reconcile_transactions::flush()
   for (transactions_list::iterator x = xacts.begin();
        x != xacts.end();
        x++) {
-    if (! cutoff || std::difftime((*x)-&gt;date(), cutoff) &lt; 0) {
+    if (! cutoff || (*x)-&gt;date() &lt; cutoff) {
       switch ((*x)-&gt;state) {
       case transaction_t::CLEARED:
 	cleared_balance += (*x)-&gt;amount;</diff>
      <filename>reconcile.cc</filename>
    </modified>
    <modified>
      <diff>@@ -8,14 +8,15 @@ namespace ledger {
 
 class reconcile_transactions : public item_handler&lt;transaction_t&gt;
 {
-  value_t balance;
-  time_t  cutoff;
+  value_t    balance;
+  datetime_t cutoff;
 
   transactions_list xacts;
 
  public:
   reconcile_transactions(item_handler&lt;transaction_t&gt; * handler,
-			 const value_t&amp; _balance, const time_t _cutoff)
+			 const value_t&amp;    _balance,
+			 const datetime_t&amp; _cutoff)
     : item_handler&lt;transaction_t&gt;(handler),
       balance(_balance), cutoff(_cutoff) {}
 </diff>
      <filename>reconcile.h</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,6 @@ report_t::report_t()
   display_predicate   = &quot;&quot;;
   descend_expr	      = &quot;&quot;;
 
-  pricing_leeway = 24 * 3600;
   budget_flags   = BUDGET_NO_BUDGET;
 
   head_entries = 0;
@@ -204,8 +203,8 @@ void report_t::process_options(const std::string&amp;     command,
 
   // Now setup the various formatting strings
 
-  if (! date_format.empty())
-    datetime_t::date_format = date_format;
+  if (! date_output_format.empty())
+    date_t::output_format = date_output_format;
 
   amount_t::keep_price = keep_price;
   amount_t::keep_date  = keep_date;
@@ -278,9 +277,9 @@ report_t::chain_xact_handlers(const std::string&amp; command,
     // transactions which can be reconciled to a given balance
     // (calculated against the transactions which it receives).
     if (! reconcile_balance.empty()) {
-      std::time_t cutoff = now;
+      datetime_t cutoff = datetime_t::now;
       if (! reconcile_date.empty())
-	parse_date(reconcile_date.c_str(), &amp;cutoff);
+	cutoff = reconcile_date;
       ptrs.push_back(formatter =
 		     new reconcile_transactions
 		     (formatter, value_t(reconcile_balance), cutoff));</diff>
      <filename>report.cc</filename>
    </modified>
    <modified>
      <diff>@@ -27,10 +27,9 @@ class report_t
   std::string forecast_limit;
   std::string reconcile_balance;
   std::string reconcile_date;
-  std::string date_format;
+  std::string date_output_format;
 
   unsigned long budget_flags;
-  unsigned long pricing_leeway;
 
   int head_entries;
   int tail_entries;</diff>
      <filename>report.h</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,6 @@
 #include &lt;fstream&gt;
 #include &lt;sstream&gt;
 #include &lt;cstring&gt;
-#include &lt;ctime&gt;
 #include &lt;cctype&gt;
 #include &lt;cstdio&gt;
 #include &lt;cstdlib&gt;
@@ -36,10 +35,15 @@ static unsigned int linenum;
 static unsigned int src_idx;
 static accounts_map account_aliases;
 
+static std::list&lt;std::pair&lt;std::string, int&gt; &gt; include_stack;
+
 #ifdef TIMELOG_SUPPORT
-static std::time_t time_in;
-static account_t * last_account;
-static std::string last_desc;
+struct time_entry_t {
+  datetime_t  checkin;
+  account_t * account;
+  std::string desc;
+};
+std::list&lt;time_entry_t&gt; time_entries;
 #endif
 
 inline char * next_element(char * buf, bool variable = false)
@@ -85,7 +89,7 @@ static value_expr parse_amount_expr(std::istream&amp; in, amount_t&amp; amount,
 
   if (! compute_amount(expr, amount, xact))
     throw new parse_error(&quot;Amount expression failed to compute&quot;);
-    
+
   if (expr-&gt;kind == value_expr_t::CONSTANT)
     expr = NULL;
 
@@ -285,12 +289,10 @@ transaction_t * parse_transaction(char * line, account_t * account,
 
 	  if (char * p = std::strchr(buf, '=')) {
 	    *p++ = '\0';
-	    if (! quick_parse_date(p, &amp;xact-&gt;_date_eff))
-	      throw new parse_error(&quot;Failed to parse effective date&quot;);
+	    xact-&gt;_date_eff = p;
 	  }
-
-	  if (buf[0] &amp;&amp; ! quick_parse_date(buf, &amp;xact-&gt;_date))
-	    throw new parse_error(&quot;Failed to parse date&quot;);
+	  if (buf[0])
+	    xact-&gt;_date = buf;
 	}
     }
   }
@@ -358,12 +360,9 @@ entry_t * parse_entry(std::istream&amp; in, char * line, account_t * master,
 
   if (char * p = std::strchr(line, '=')) {
     *p++ = '\0';
-    if (! quick_parse_date(p, &amp;curr-&gt;_date_eff))
-      throw new parse_error(&quot;Failed to parse effective date&quot;);
+    curr-&gt;_date_eff = p;
   }
-
-  if (! quick_parse_date(line, &amp;curr-&gt;_date))
-    throw new parse_error(&quot;Failed to parse date&quot;);
+  curr-&gt;_date = line;
 
   TIMER_STOP(entry_date);
 
@@ -492,22 +491,61 @@ bool textual_parser_t::test(std::istream&amp; in) const
   return true;
 }
 
-static void clock_out_from_timelog(const std::time_t when,
-				   journal_t * journal)
+static void clock_out_from_timelog(const datetime_t&amp; when,
+				   account_t *	account,
+				   const char *	desc,
+				   journal_t *	journal)
 {
+  time_entry_t event;
+  bool found = false;
+
+  if (time_entries.size() == 1) {
+    event = time_entries.back();
+    time_entries.clear();
+  }
+  else if (time_entries.empty()) {
+    throw new parse_error(&quot;Timelog check-out event without a check-in&quot;);
+  }
+  else if (! account) {
+    throw new parse_error
+      (&quot;When multiple check-ins are active, checking out requires an account&quot;);
+  }
+  else {
+    for (std::list&lt;time_entry_t&gt;::iterator i = time_entries.begin();
+	 i != time_entries.end();
+	 i++)
+      if (account == (*i).account) {
+	event = *i;
+	found = true;
+	time_entries.erase(i);
+	break;
+      }
+    if (! found)
+      throw new parse_error
+	(&quot;Timelog check-out event does not match any current check-ins&quot;);
+  }
+
+  if (desc &amp;&amp; event.desc.empty()) {
+    event.desc = desc;
+    desc = NULL;
+  }
+
   std::auto_ptr&lt;entry_t&gt; curr(new entry_t);
   curr-&gt;_date = when;
-  curr-&gt;code  = &quot;&quot;;
-  curr-&gt;payee = last_desc;
+  curr-&gt;code  = desc ? desc : &quot;&quot;;
+  curr-&gt;payee = event.desc;
 
-  double diff = std::difftime(curr-&gt;_date, time_in);
-  char   buf[32];
-  std::sprintf(buf, &quot;%lds&quot;, long(diff));
+  if (curr-&gt;_date &lt; event.checkin)
+    throw new parse_error
+      (&quot;Timelog check-out date less than corresponding check-in&quot;);
+
+  char buf[32];
+  std::sprintf(buf, &quot;%lds&quot;, curr-&gt;_date - event.checkin);
   amount_t amt;
   amt.parse(buf);
 
   transaction_t * xact
-    = new transaction_t(last_account, amt, TRANSACTION_VIRTUAL);
+    = new transaction_t(event.account, amt, TRANSACTION_VIRTUAL);
   xact-&gt;state = transaction_t::CLEARED;
   curr-&gt;add_transaction(xact);
 
@@ -517,8 +555,6 @@ static void clock_out_from_timelog(const std::time_t when,
     curr.release();
 }
 
-static std::list&lt;std::pair&lt;std::string, int&gt; &gt; include_stack;
-
 unsigned int textual_parser_t::parse(std::istream&amp;	 in,
 				     config_t&amp;           config,
 				     journal_t *	 journal,
@@ -577,37 +613,38 @@ unsigned int textual_parser_t::parse(std::istream&amp;	 in,
 
 	char * p = skip_ws(line + 22);
 	char * n = next_element(p, true);
-	last_desc = n ? n : &quot;&quot;;
 
-	struct std::tm when;
-	if (strptime(date.c_str(), &quot;%Y/%m/%d %H:%M:%S&quot;, &amp;when)) {
-	  time_in      = std::mktime(&amp;when);
-	  last_account = account_stack.front()-&gt;find_account(p);
-	} else {
-	  last_account = NULL;
-	  throw new parse_error(&quot;Cannot parse timelog entry date&quot;);
-	}
+	time_entry_t event;
+	event.desc    = n ? n : &quot;&quot;;
+	event.checkin = date;
+	event.account = account_stack.front()-&gt;find_account(p);
+
+	if (! time_entries.empty())
+	  for (std::list&lt;time_entry_t&gt;::iterator i = time_entries.begin();
+	       i != time_entries.end();
+	       i++)
+	    if (event.account == (*i).account)
+	      throw new parse_error
+		(&quot;Cannot double check-in to the same account&quot;);
+
+	time_entries.push_back(event);
 	break;
       }
 
       case 'o':
       case 'O':
-	if (last_account) {
+	if (time_entries.empty()) {
+	  throw new parse_error(&quot;Timelog check-out event without a check-in&quot;);
+	} else {
 	  std::string date(line, 2, 19);
 
 	  char * p = skip_ws(line + 22);
-	  if (last_desc.empty() &amp;&amp; *p)
-	    last_desc = p;
+	  char * n = next_element(p, true);
 
-	  struct std::tm when;
-	  if (strptime(date.c_str(), &quot;%Y/%m/%d %H:%M:%S&quot;, &amp;when)) {
-	    clock_out_from_timelog(std::mktime(&amp;when), journal);
-	    count++;
-	  } else {
-	    throw new parse_error(&quot;Cannot parse timelog entry date&quot;);
-	  }
-
-	  last_account = NULL;
+	  clock_out_from_timelog
+	    (date, p ? account_stack.front()-&gt;find_account(p) : NULL, n,
+	     journal);
+	  count++;
 	}
 	break;
 #endif // TIMELOG_SUPPORT
@@ -631,39 +668,21 @@ unsigned int textual_parser_t::parse(std::istream&amp;	 in,
 	break;
 
       case 'P': {		// a pricing entry
-	char * date_field = skip_ws(line + 1);
-	char * time_field = next_element(date_field);
-	if (! time_field) break;
+	char * date_field_ptr = skip_ws(line + 1);
+	char * time_field_ptr = next_element(date_field_ptr);
+	if (! time_field_ptr) break;
+	std::string date_field = date_field_ptr;
 
-	char *	       symbol_and_price;
-	std::time_t    date;
-	struct std::tm when;
+	char *     symbol_and_price;
+	datetime_t datetime;
 
-	if (std::isdigit(time_field[0])) {
-	  symbol_and_price = next_element(time_field);
+	if (std::isdigit(time_field_ptr[0])) {
+	  symbol_and_price = next_element(time_field_ptr);
 	  if (! symbol_and_price) break;
-
-	  char date_buffer[64];
-	  std::strcpy(date_buffer, date_field);
-	  date_buffer[std::strlen(date_field)] = ' ';
-	  std::strcpy(&amp;date_buffer[std::strlen(date_field) + 1], time_field);
-
-	  if (strptime(date_buffer, &quot;%Y/%m/%d %H:%M:%S&quot;, &amp;when)) {
-	    date = std::mktime(&amp;when);
-	  } else {
-	    throw new parse_error(&quot;Failed to parse date/time&quot;);
-	  }
+	  datetime = date_field + &quot; &quot; + time_field_ptr;
 	} else {
-	  symbol_and_price = time_field;
-
-	  if (strptime(date_field, &quot;%Y/%m/%d&quot;, &amp;when)) {
-	    when.tm_hour = 0;
-	    when.tm_min	 = 0;
-	    when.tm_sec	 = 0;
-	    date = std::mktime(&amp;when);
-	  } else {
-	    throw new parse_error(&quot;Failed to parse date&quot;);
-	  }
+	  symbol_and_price = time_field_ptr;
+	  datetime = date_t(date_field);
 	}
 
 	std::string symbol;
@@ -671,7 +690,7 @@ unsigned int textual_parser_t::parse(std::istream&amp;	 in,
 	amount_t price(symbol_and_price);
 
 	if (commodity_t * commodity = commodity_t::find_or_create(symbol))
-	  commodity-&gt;add_price(date, price);
+	  commodity-&gt;add_price(datetime, price);
 	break;
       }
 
@@ -686,7 +705,7 @@ unsigned int textual_parser_t::parse(std::istream&amp;	 in,
       }
 
       case 'Y':                   // set the current year
-	now_year = std::atoi(skip_ws(line + 1)) - 1900;
+	date_t::current_year = std::atoi(skip_ws(line + 1)) - 1900;
 	break;
 
 #ifdef TIMELOG_SUPPORT
@@ -858,9 +877,12 @@ unsigned int textual_parser_t::parse(std::istream&amp;	 in,
   }
 
  done:
-  if (last_account) {
-    clock_out_from_timelog(now, journal);
-    last_account = NULL;
+  if (! time_entries.empty()) {
+    for (std::list&lt;time_entry_t&gt;::iterator i = time_entries.begin();
+	 i != time_entries.end();
+	 i++)
+      clock_out_from_timelog(datetime_t::now, (*i).account, NULL, journal);
+    time_entries.clear();
   }
 
   if (added_auto_entry_hook)</diff>
      <filename>textual.cc</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@ value_expr amount_expr;
 value_expr total_expr;
 
 std::auto_ptr&lt;scope_t&gt; global_scope;
-std::time_t terminus;
+datetime_t terminus;
 
 details_t::details_t(const transaction_t&amp; _xact)
   : entry(_xact.entry), xact(&amp;_xact), account(xact_account(_xact))
@@ -150,7 +150,7 @@ void value_expr_t::compute(value_t&amp; result, const details_t&amp; details,
     break;
 
   case F_NOW:
-    result = datetime_t(terminus);
+    result = terminus;
     break;
 
   case AMOUNT:
@@ -257,37 +257,37 @@ void value_expr_t::compute(value_t&amp; result, const details_t&amp; details,
   case DATE:
     if (details.xact &amp;&amp; transaction_has_xdata(*details.xact) &amp;&amp;
 	transaction_xdata_(*details.xact).date)
-      result = datetime_t(transaction_xdata_(*details.xact).date);
+      result = transaction_xdata_(*details.xact).date;
     else if (details.xact)
-      result = datetime_t(details.xact-&gt;date());
+      result = details.xact-&gt;date();
     else if (details.entry)
-      result = datetime_t(details.entry-&gt;date());
+      result = details.entry-&gt;date();
     else
-      result = datetime_t(terminus);
+      result = terminus;
     break;
 
   case ACT_DATE:
     if (details.xact &amp;&amp; transaction_has_xdata(*details.xact) &amp;&amp;
 	transaction_xdata_(*details.xact).date)
-      result = datetime_t(transaction_xdata_(*details.xact).date);
+      result = transaction_xdata_(*details.xact).date;
     else if (details.xact)
-      result = datetime_t(details.xact-&gt;actual_date());
+      result = details.xact-&gt;actual_date();
     else if (details.entry)
-      result = datetime_t(details.entry-&gt;actual_date());
+      result = details.entry-&gt;actual_date();
     else
-      result = datetime_t(terminus);
+      result = terminus;
     break;
 
   case EFF_DATE:
     if (details.xact &amp;&amp; transaction_has_xdata(*details.xact) &amp;&amp;
 	transaction_xdata_(*details.xact).date)
-      result = datetime_t(transaction_xdata_(*details.xact).date);
+      result = transaction_xdata_(*details.xact).date;
     else if (details.xact)
-      result = datetime_t(details.xact-&gt;effective_date());
+      result = details.xact-&gt;effective_date();
     else if (details.entry)
-      result = datetime_t(details.entry-&gt;effective_date());
+      result = details.entry-&gt;effective_date();
     else
-      result = datetime_t(terminus);
+      result = terminus;
     break;
 
   case CLEARED:
@@ -388,19 +388,20 @@ void value_expr_t::compute(value_t&amp; result, const details_t&amp; details,
     value_expr_t * expr = find_leaf(context, 0, arg_index);
     expr-&gt;compute(result, details, context);
 
-    // jww (2006-03-05): Generate an error if result is not a DATETIME
-    std::time_t moment = (long)result;
-    struct std::tm * desc = std::localtime(&amp;moment);
+    if (result.type != value_t::DATETIME)
+      throw new compute_error(&quot;Invalid date passed to year|month|day(date)&quot;,
+			      new valexpr_context(expr));
 
+    datetime_t&amp; moment(*((datetime_t *)result.data));
     switch (kind) {
     case F_YEAR:
-      result = (long)desc-&gt;tm_year + 1900L;
+      result = (long)moment.year();
       break;
     case F_MONTH:
-      result = (long)desc-&gt;tm_mon + 1L;
+      result = (long)moment.month();
       break;
     case F_DAY:
-      result = (long)desc-&gt;tm_mday;
+      result = (long)moment.day();
       break;
     }
     break;
@@ -1036,7 +1037,7 @@ value_expr_t * parse_value_term(std::istream&amp; in, scope_t * scope,
 
     node.reset(new value_expr_t(value_expr_t::CONSTANT));
     interval_t timespan(buf);
-    node-&gt;value = new value_t(datetime_t(timespan.first()));
+    node-&gt;value = new value_t(timespan.first());
     break;
   }
 </diff>
      <filename>valexpr.cc</filename>
    </modified>
    <modified>
      <diff>@@ -224,7 +224,7 @@ struct scope_t
 
   typedef std::map&lt;const std::string, value_expr_t *&gt;  symbol_map;
   typedef std::pair&lt;const std::string, value_expr_t *&gt; symbol_pair;
-  
+
   symbol_map symbols;
 
   scope_t(scope_t * _parent = NULL) : parent(_parent) {
@@ -267,8 +267,8 @@ struct scope_t
 
 extern std::auto_ptr&lt;scope_t&gt; global_scope;
 
-extern std::time_t terminus;
-extern bool	   initialized;
+extern datetime_t terminus;
+extern bool	  initialized;
 
 void init_value_expr();
 </diff>
      <filename>valexpr.h</filename>
    </modified>
    <modified>
      <diff>@@ -836,7 +836,7 @@ value_t::operator double() const
   case INTEGER:
     return *((long *) data);
   case DATETIME:
-    return *((datetime_t *) data);
+    throw new value_error(&quot;Cannot convert a date/time to a double&quot;);
   case AMOUNT:
     return *((amount_t *) data);
   case BALANCE:
@@ -1111,7 +1111,7 @@ void value_t::abs()
   }
 }
 
-value_t value_t::value(const std::time_t moment) const
+value_t value_t::value(const datetime_t&amp; moment) const
 {
   switch (type) {
   case BOOLEAN:
@@ -1225,18 +1225,18 @@ value_t value_t::date() const
   case BOOLEAN:
     throw new value_error(&quot;Cannot find the date of a boolean&quot;);
   case INTEGER:
-    return 0L;
+    return datetime_t();
   case DATETIME:
     return *this;
 
   case AMOUNT:
-    return ((amount_t *) data)-&gt;date();
+    return datetime_t(((amount_t *) data)-&gt;date());
 
   case BALANCE:
-    return (long)((balance_t *) data)-&gt;date();
+    return datetime_t(((balance_t *) data)-&gt;date());
 
   case BALANCE_PAIR:
-    return (long)((balance_pair_t *) data)-&gt;quantity.date();
+    return datetime_t(((balance_pair_t *) data)-&gt;quantity.date());
 
   default:
     assert(0);</diff>
      <filename>value.cc</filename>
    </modified>
    <modified>
      <diff>@@ -315,7 +315,7 @@ class value_t
 			    const bool keep_tag   = amount_t::keep_tag) const;
 
   value_t&amp; add(const amount_t&amp;  amount, const amount_t * cost = NULL);
-  value_t  value(const std::time_t moment) const;
+  value_t  value(const datetime_t&amp; moment) const;
   void     reduce();
 
   value_t reduced() const {</diff>
      <filename>value.h</filename>
    </modified>
    <modified>
      <diff>@@ -183,7 +183,7 @@ void handle_value(const value_t&amp;	       value,
 		  unsigned int		       flags,
 		  std::list&lt;transaction_t&gt;&amp;    temps,
 		  item_handler&lt;transaction_t&gt;&amp; handler,
-		  const std::time_t            date = 0,
+		  const datetime_t&amp;            date = datetime_t(),
 		  transactions_list *          component_xacts = NULL)
 {
   temps.push_back(transaction_t(account));
@@ -312,7 +312,7 @@ void related_transactions::flush()
   item_handler&lt;transaction_t&gt;::flush();
 }
 
-void changed_value_transactions::output_diff(const std::time_t current)
+void changed_value_transactions::output_diff(const datetime_t&amp; current)
 {
   value_t cur_bal;
 
@@ -335,7 +335,7 @@ void changed_value_transactions::output_diff(const std::time_t current)
 void changed_value_transactions::operator()(transaction_t&amp; xact)
 {
   if (last_xact) {
-    std::time_t moment = 0;
+    datetime_t moment;
     if (transaction_has_xdata(*last_xact))
       moment = transaction_xdata_(*last_xact).date;
     else
@@ -367,19 +367,18 @@ void component_transactions::operator()(transaction_t&amp; xact)
 
 void subtotal_transactions::report_subtotal(const char * spec_fmt)
 {
-  char buf[256];
-
+  std::ostringstream out_date;
   if (! spec_fmt) {
     std::string fmt = &quot;- &quot;;
-    fmt += datetime_t::date_format;
-    std::strftime(buf, 255, fmt.c_str(), std::localtime(&amp;finish));
+    fmt += date_t::output_format;
+    finish.write(out_date, fmt);
   } else {
-    std::strftime(buf, 255, spec_fmt, std::localtime(&amp;finish));
+    finish.write(out_date, spec_fmt);
   }
 
   entry_temps.push_back(entry_t());
   entry_t&amp; entry = entry_temps.back();
-  entry.payee = buf;
+  entry.payee = out_date.str();
   entry._date = start;
 
   for (values_map::iterator i = values.begin();
@@ -393,9 +392,9 @@ void subtotal_transactions::report_subtotal(const char * spec_fmt)
 
 void subtotal_transactions::operator()(transaction_t&amp; xact)
 {
-  if (! start || std::difftime(xact.date(), start) &lt; 0)
+  if (! start || xact.date() &lt; start)
     start = xact.date();
-  if (! finish || std::difftime(xact.date(), finish) &gt; 0)
+  if (! finish || xact.date() &gt; finish)
     finish = xact.date();
 
   account_t * acct = xact_account(xact);
@@ -429,13 +428,13 @@ void subtotal_transactions::operator()(transaction_t&amp; xact)
     account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
 }
 
-void interval_transactions::report_subtotal(const std::time_t moment)
+void interval_transactions::report_subtotal(const datetime_t&amp; moment)
 {
   assert(last_xact);
 
   start = interval.begin;
   if (moment)
-    finish = moment - 86400;
+    finish = moment - 86400L;
   else
     finish = last_xact-&gt;date();
 
@@ -446,10 +445,10 @@ void interval_transactions::report_subtotal(const std::time_t moment)
 
 void interval_transactions::operator()(transaction_t&amp; xact)
 {
-  const std::time_t date = xact.date();
+  const datetime_t date = xact.date();
 
-  if ((interval.begin &amp;&amp; std::difftime(date, interval.begin) &lt; 0) ||
-      (interval.end   &amp;&amp; std::difftime(date, interval.end) &gt;= 0))
+  if ((interval.begin &amp;&amp; date &lt; interval.begin) ||
+      (interval.end   &amp;&amp; date &gt;= interval.end))
     return;
 
   if (interval) {
@@ -460,13 +459,13 @@ void interval_transactions::operator()(transaction_t&amp; xact)
       started = true;
     }
 
-    std::time_t quant = interval.increment(interval.begin);
-    if (std::difftime(date, quant) &gt;= 0) {
+    datetime_t quant = interval.increment(interval.begin);
+    if (date &gt;= quant) {
       if (last_xact)
 	report_subtotal(quant);
 
-      std::time_t temp;
-      while (std::difftime(date, temp = interval.increment(quant)) &gt;= 0) {
+      datetime_t temp;
+      while (date &gt;= (temp = interval.increment(quant))) {
 	if (quant == temp)
 	  break;
 	quant = temp;
@@ -518,7 +517,7 @@ void by_payee_transactions::operator()(transaction_t&amp; xact)
     i = result.first;
   }
 
-  if (std::difftime(xact.date(), (*i).second-&gt;start) &gt; 0)
+  if (xact.date() &gt; (*i).second-&gt;start)
     (*i).second-&gt;start = xact.date();
 
   (*(*i).second)(xact);
@@ -602,7 +601,7 @@ void generate_transactions::add_transaction(const interval_t&amp; period,
   pending_xacts.push_back(pending_xacts_pair(period, &amp;xact));
 }
 
-void budget_transactions::report_budget_items(const std::time_t moment)
+void budget_transactions::report_budget_items(const datetime_t&amp; moment)
 {
   if (pending_xacts.size() == 0)
     return;
@@ -613,14 +612,14 @@ void budget_transactions::report_budget_items(const std::time_t moment)
     for (pending_xacts_list::iterator i = pending_xacts.begin();
 	 i != pending_xacts.end();
 	 i++) {
-      std::time_t&amp; begin = (*i).first.begin;
+      datetime_t&amp; begin = (*i).first.begin;
       if (! begin) {
 	(*i).first.start(moment);
 	begin = (*i).first.begin;
       }
 
-      if (std::difftime(begin, moment) &lt; 0 &amp;&amp;
-	  (! (*i).first.end || std::difftime(begin, (*i).first.end) &lt; 0)) {
+      if (begin &lt; moment &amp;&amp;
+	  (! (*i).first.end || begin &lt; (*i).first.end)) {
 	transaction_t&amp; xact = *(*i).second;
 
 	DEBUG_PRINT(&quot;ledger.walk.budget&quot;, &quot;Reporting budget for &quot;
@@ -687,10 +686,10 @@ void forecast_transactions::add_transaction(const interval_t&amp; period,
 
   interval_t&amp; i = pending_xacts.back().first;
   if (! i.begin) {
-    i.start(now);
+    i.start(datetime_t::now);
     i.begin = i.increment(i.begin);
   } else {
-    while (std::difftime(i.begin, now) &lt; 0)
+    while (i.begin &lt; datetime_t::now)
       i.begin = i.increment(i.begin);
   }
 }
@@ -698,20 +697,19 @@ void forecast_transactions::add_transaction(const interval_t&amp; period,
 void forecast_transactions::flush()
 {
   transactions_list passed;
-  std::time_t       last = 0;
+  datetime_t last;
 
   while (pending_xacts.size() &gt; 0) {
     pending_xacts_list::iterator least = pending_xacts.begin();
     for (pending_xacts_list::iterator i = ++pending_xacts.begin();
 	 i != pending_xacts.end();
 	 i++)
-      if (std::difftime((*i).first.begin, (*least).first.begin) &lt; 0)
+      if ((*i).first.begin &lt; (*least).first.begin)
 	least = i;
 
-    std::time_t&amp; begin = (*least).first.begin;
+    datetime_t&amp; begin = (*least).first.begin;
 
-    if ((*least).first.end &amp;&amp;
-	std::difftime(begin, (*least).first.end) &gt;= 0) {
+    if ((*least).first.end &amp;&amp; begin &gt;= (*least).first.end) {
       pending_xacts.erase(least);
       passed.remove((*least).second);
       continue;
@@ -731,9 +729,9 @@ void forecast_transactions::flush()
     temp.flags |= TRANSACTION_BULK_ALLOC;
     entry.add_transaction(&amp;temp);
 
-    std::time_t next = (*least).first.increment(begin);
-    if (std::difftime(next, begin) &lt; 0 || // wraparound
-	(last &amp;&amp; std::difftime(next, last) &gt; 5 * 365 * 24 * 60 * 60))
+    datetime_t next = (*least).first.increment(begin);
+    if (next &lt; begin || // wraparound
+	(last &amp;&amp; (next - last) &gt; 365 * 5 * 24 * 3600))
       break;
     begin = next;
 </diff>
      <filename>walk.cc</filename>
    </modified>
    <modified>
      <diff>@@ -90,15 +90,15 @@ struct transaction_xdata_t
   value_t	 value;
   unsigned int   index;
   unsigned short dflags;
-  std::time_t    date;
+  datetime_t     date;
   account_t *    account;
   void *         ptr;
 
   transactions_list * component_xacts;
 
   transaction_xdata_t()
-    : index(0), dflags(0), date(0), account(NULL), ptr(NULL),
-      component_xacts(NULL) {
+    : index(0), dflags(0),
+      account(NULL), ptr(NULL), component_xacts(NULL) {
     DEBUG_PRINT(&quot;ledger.memory.ctors&quot;, &quot;ctor transaction_xdata_t &quot; &lt;&lt; this);
   }
 
@@ -445,13 +445,13 @@ class changed_value_transactions : public item_handler&lt;transaction_t&gt;
 
   virtual void flush() {
     if (last_xact) {
-      output_diff(now);
+      output_diff(datetime_t::now);
       last_xact = NULL;
     }
     item_handler&lt;transaction_t&gt;::flush();
   }
 
-  void output_diff(const std::time_t current);
+  void output_diff(const datetime_t&amp; current);
 
   virtual void operator()(transaction_t&amp; xact);
 };
@@ -481,13 +481,13 @@ class subtotal_transactions : public item_handler&lt;transaction_t&gt;
   std::list&lt;transaction_t&gt; xact_temps;
 
  public:
-  std::time_t start;
-  std::time_t finish;
+  datetime_t start;
+  datetime_t finish;
 
   subtotal_transactions(item_handler&lt;transaction_t&gt; * handler,
 			bool _remember_components = false)
     : item_handler&lt;transaction_t&gt;(handler),
-      remember_components(_remember_components), start(0), finish(0) {}
+      remember_components(_remember_components) {}
 #ifdef DEBUG_ENABLED
   subtotal_transactions(const subtotal_transactions&amp;) {
     assert(0);
@@ -534,7 +534,7 @@ class interval_transactions : public subtotal_transactions
     : subtotal_transactions(_handler, remember_components),
       interval(_interval), last_xact(NULL), started(false) {}
 
-  void report_subtotal(const std::time_t moment = 0);
+  void report_subtotal(const datetime_t&amp; moment = datetime_t());
 
   virtual void flush() {
     if (last_xact)
@@ -606,9 +606,7 @@ class dow_transactions : public subtotal_transactions
 
   virtual void flush();
   virtual void operator()(transaction_t&amp; xact) {
-    std::time_t when = xact.date();
-    struct std::tm * desc = std::localtime(&amp;when);
-    days_of_the_week[desc-&gt;tm_wday].push_back(&amp;xact);
+    days_of_the_week[xact.date().wday()].push_back(&amp;xact);
   }
 };
 
@@ -648,7 +646,7 @@ class budget_transactions : public generate_transactions
 		      unsigned long _flags = BUDGET_BUDGETED)
     : generate_transactions(handler), flags(_flags) {}
 
-  void report_budget_items(const std::time_t moment);
+  void report_budget_items(const datetime_t&amp; moment);
 
   virtual void operator()(transaction_t&amp; xact);
 };</diff>
      <filename>walk.h</filename>
    </modified>
    <modified>
      <diff>@@ -12,13 +12,13 @@ extern &quot;C&quot; {
 #include &lt;expat.h&gt;           // expat XML parser
 #elif defined(HAVE_XMLPARSE)
 #include &lt;xmlparse.h&gt;        // expat XML parser
-#else
-#error &quot;No XML parser library defined.&quot;
 #endif
 }
 
 namespace ledger {
 
+#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
+
 static XML_Parser    current_parser;
 static unsigned int  count;
 
@@ -83,10 +83,10 @@ static void endElement(void *userData, const char *name)
     curr_entry = NULL;
   }
   else if (std::strcmp(name, &quot;en:date&quot;) == 0) {
-    quick_parse_date(data.c_str(), &amp;curr_entry-&gt;_date);
+    curr_entry-&gt;_date = data;
   }
   else if (std::strcmp(name, &quot;en:date_eff&quot;) == 0) {
-    quick_parse_date(data.c_str(), &amp;curr_entry-&gt;_date_eff);
+    curr_entry-&gt;_date_eff = data;
   }
   else if (std::strcmp(name, &quot;en:code&quot;) == 0) {
     curr_entry-&gt;code = data;
@@ -246,6 +246,8 @@ unsigned int xml_parser_t::parse(std::istream&amp;	     in,
   return count;
 }
 
+#endif // defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
+
 void xml_write_amount(std::ostream&amp; out, const amount_t&amp; amount,
 		      const int depth = 0)
 {
@@ -367,16 +369,14 @@ void output_xml_string(std::ostream&amp; out, const std::string&amp; str)
 
 void format_xml_entries::format_last_entry()
 {
-  char buf[32];
-  std::strftime(buf, 31, &quot;%Y/%m/%d&quot;, std::localtime(&amp;last_entry-&gt;_date));
-
   output_stream &lt;&lt; &quot;  &lt;entry&gt;\n&quot;
-		&lt;&lt; &quot;    &lt;en:date&gt;&quot; &lt;&lt; buf &lt;&lt; &quot;&lt;/en:date&gt;\n&quot;;
+		&lt;&lt; &quot;    &lt;en:date&gt;&quot; &lt;&lt; last_entry-&gt;_date.to_string(&quot;%Y/%m/%d&quot;)
+		&lt;&lt; &quot;&lt;/en:date&gt;\n&quot;;
 
-  if (last_entry-&gt;_date_eff) {
-    std::strftime(buf, 31, &quot;%Y/%m/%d&quot;, std::localtime(&amp;last_entry-&gt;_date_eff));
-    output_stream &lt;&lt; &quot;    &lt;en:date_eff&gt;&quot; &lt;&lt; buf &lt;&lt; &quot;&lt;/en:date_eff&gt;\n&quot;;
-  }
+  if (last_entry-&gt;_date_eff)
+    output_stream &lt;&lt; &quot;    &lt;en:date_eff&gt;&quot;
+		  &lt;&lt; last_entry-&gt;_date_eff.to_string(&quot;%Y/%m/%d&quot;)
+		  &lt;&lt; &quot;&lt;/en:date_eff&gt;\n&quot;;
 
   if (! last_entry-&gt;code.empty()) {
     output_stream &lt;&lt; &quot;    &lt;en:code&gt;&quot;;
@@ -403,14 +403,15 @@ void format_xml_entries::format_last_entry()
 
       output_stream &lt;&lt; &quot;      &lt;transaction&gt;\n&quot;;
 
-      if ((*i)-&gt;_date) {
-	std::strftime(buf, 31, &quot;%Y/%m/%d&quot;, std::localtime(&amp;(*i)-&gt;_date));
-	output_stream &lt;&lt; &quot;        &lt;tr:date&gt;&quot; &lt;&lt; buf &lt;&lt; &quot;&lt;/tr:date&gt;\n&quot;;
-      }
-      if ((*i)-&gt;_date_eff) {
-	std::strftime(buf, 31, &quot;%Y/%m/%d&quot;, std::localtime(&amp;(*i)-&gt;_date_eff));
-	output_stream &lt;&lt; &quot;        &lt;tr:date_eff&gt;&quot; &lt;&lt; buf &lt;&lt; &quot;&lt;/tr:date_eff&gt;\n&quot;;
-      }
+      if ((*i)-&gt;_date)
+	output_stream &lt;&lt; &quot;        &lt;tr:date&gt;&quot;
+		      &lt;&lt; (*i)-&gt;_date.to_string(&quot;%Y/%m/%d&quot;)
+		      &lt;&lt; &quot;&lt;/tr:date&gt;\n&quot;;
+
+      if ((*i)-&gt;_date_eff)
+	output_stream &lt;&lt; &quot;        &lt;tr:date_eff&gt;&quot;
+		      &lt;&lt; (*i)-&gt;_date_eff.to_string(&quot;%Y/%m/%d&quot;)
+		      &lt;&lt; &quot;&lt;/tr:date_eff&gt;\n&quot;;
 
       if ((*i)-&gt;state == transaction_t::CLEARED)
 	output_stream &lt;&lt; &quot;        &lt;tr:cleared/&gt;\n&quot;;</diff>
      <filename>xml.cc</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c3c401ac0f43dfb3f71b818b45ef47578e6d390b</id>
    </parent>
  </parents>
  <author>
    <name>John Wiegley</name>
    <email>johnw@newartisans.com</email>
  </author>
  <url>http://github.com/jwiegley/ledger/commit/5a93d4819e5fc753352618b729e0fe45532166b9</url>
  <id>5a93d4819e5fc753352618b729e0fe45532166b9</id>
  <committed-date>2008-04-12T23:41:32-07:00</committed-date>
  <authored-date>2006-03-27T21:24:02-08:00</authored-date>
  <message>Reworked the way date/times are handled.</message>
  <tree>200220bfcc5642a9efd8847001aeac889ed79e7d</tree>
  <committer>
    <name>John Wiegley</name>
    <email>johnw@newartisans.com</email>
  </committer>
</commit>
