date decoding fixes and tests
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index bb53c24..bbcf2cd 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -338,7 +338,9 @@
       double      dfnum;
       /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */
       float       fnum;
-      /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH. */
+      /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH.
+          Floating-point dates that are NaN, +Inifinity or -Inifinity
+          decode with the @ref QCBOR_ERR_DATE_OVERFLOW error. */
       struct {
          int64_t  nSeconds;
          double   fSecondsFraction;
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 9af3a59..2b4ded7 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -640,21 +640,25 @@
  @brief Decode the next item as an epoch date.
 
  @param[in] pCtx             The decode context.
- @param[in] uTagRequirement  One of @c QCBOR_TAGSPEC_MATCH_XXX.
- @param[out] pnTime            The decoded URI.
+ @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ @param[out] pnTime            The decoded epoch date.
+
+ This will handle floating-point dates, but always returns them as an int64_t
+ discarding the fractional part. Use QCBORDecode_GetNext() instead of this to get the
+ fractional part.
 
  See @ref Decode-Errors for discussion on how error handling works.
 
  See @ref Tag-Matcing for discussion on tag requirements.
 */
-void QCBORDecode_GetEpocDate(QCBORDecodeContext *pCtx,
+void QCBORDecode_GetEpochDate(QCBORDecodeContext *pCtx,
                              uint8_t             uTagRequirement,
                              int64_t            *pnTime);
 
-static void QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pCtx,
-                                           int64_t             nLabel,
-                                           uint8_t             uTagRequirement,
-                                           int64_t            *pnTime);
+void QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pCtx,
+                                    int64_t             nLabel,
+                                    uint8_t             uTagRequirement,
+                                    int64_t            *pnTime);
 
 void QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pCtx,
                                      const char         *szLabel,
@@ -694,7 +698,7 @@
  QCBORDecode_GetUInt64ConvertAll() and
  QCBORDecode_GetDoubleConvertAll() which can convert big numbers.
 */
-// Improveent: Add function that at least convert integers
+// Improvement: Add function that at least convert integers to big nums
 void QCBORDecode_GetBignum(QCBORDecodeContext *pCtx,
                            uint8_t             uTagRequirement,
                            UsefulBufC         *pValue,
@@ -961,8 +965,8 @@
  Note that this doesn not actually remove the base64 encoding.
 */
 static void QCBORDecode_GetB64URL(QCBORDecodeContext *pCtx,
-                                    uint8_t             uTagRequirement,
-                                    UsefulBufC         *pB64Text);
+                                  uint8_t             uTagRequirement,
+                                  UsefulBufC         *pB64Text);
 
 static void QCBORDecode_GetB64URLInMapN(QCBORDecodeContext *pCtx,
                                         int64_t             nLabel,
@@ -1075,7 +1079,13 @@
 
  This puts the decoder in bounded mode which narrows
  decoding to the map entered and enables
- getting items by label.
+ getting items by label.  Note that all items
+ in the map must be well-formed and valid to be
+ able to search it by label because a full traversal
+ is done for each search. If not, the search will
+ retun an error for the item that is not well-formed
+ and valid. This may not be the item with the label
+ that is the subject of the search.
 
  Nested maps can be decoded like this by entering
  each map in turn.
@@ -1697,6 +1707,7 @@
 
 // Semi private
 #define QCBOR_TAGSPEC_NUM_TYPES 3
+// TODO: make content types 4 to help out epoch dates?
 /* TODO: This structure can probably be rearranged so the initialization
  of it takes much less code. */
 typedef struct {
@@ -2196,27 +2207,6 @@
 }
 
 
-inline static void
-QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
-                               int64_t             nLabel,
-                               uint8_t             uTagRequirement,
-                               int64_t            *puTime)
-{
-   const TagSpecification TagSpec =
-      {
-         uTagRequirement,
-         {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
-         {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_NONE}
-      };
-
-   QCBORItem Item;
-   QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
-   *puTime = Item.val.int64; // TODO: lots of work to do here to
-   // handle the variety of date types
-   // This can't stay as an inline function. May have to rewrite date handling
-}
-
-
 
 #ifdef __cplusplus
 }
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 34d4dbc..00b10cb 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -33,7 +33,11 @@
 
 #include "qcbor/qcbor_decode.h"
 #include "qcbor/qcbor_spiffy_decode.h"
-#include "ieee754.h"
+#include "ieee754.h" // Does not use math.h
+
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+#include <math.h> // For isnan(). TODO: list
+#endif
 
 
 /*
@@ -1549,7 +1553,7 @@
  */
 static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
 {
-   QCBORError nReturn = QCBOR_SUCCESS;
+   QCBORError uReturn = QCBOR_SUCCESS;
 
    pDecodedItem->val.epochDate.fSecondsFraction = 0;
 
@@ -1560,11 +1564,10 @@
          break;
 
       case QCBOR_TYPE_UINT64:
-         if(pDecodedItem->val.uint64 > INT64_MAX) {
-            nReturn = QCBOR_ERR_DATE_OVERFLOW;
-            goto Done;
-         }
-         pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
+         // This only happens for CBOR type 0 > INT64_MAX so it is
+         // always an overflow.
+         uReturn = QCBOR_ERR_DATE_OVERFLOW;
+         goto Done;
          break;
 
       case QCBOR_TYPE_DOUBLE:
@@ -1590,13 +1593,16 @@
          //
          // Without the 0x7ff there is a ~30 minute range of time
          // values 10 billion years in the past and in the future
-         // where this this code would go wrong and some compilers
-         // will generate warnings or errors.
+         // where this code would go wrong. Some compilers
+         // will generate warnings or errors without the 0x7ff
+         // because of the precision issue.
          const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
                             pDecodedItem->val.dfnum :
                             (double)pDecodedItem->val.fnum;
-         if(d > (double)(INT64_MAX - 0x7ff)) {
-            nReturn = QCBOR_ERR_DATE_OVERFLOW;
+         if(isnan(d) ||
+            d > (double)(INT64_MAX - 0x7ff) ||
+            d < (double)(INT64_MIN + 0x7ff)) {
+            uReturn = QCBOR_ERR_DATE_OVERFLOW;
             goto Done;
          }
          pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
@@ -1604,24 +1610,23 @@
                            d - (double)pDecodedItem->val.epochDate.nSeconds;
       }
 #else
-         /* Disabling float support causes a floating point
-          data to error in the default below. The above code
-          requires floating point conversion to integers and
-          comparison which requires either floating point HW
+         /* Disabling float support causes a floating-point
+          date to error in the default below. The above code
+          requires floating-point conversion to integers and
+          comparison which requires either floating-point HW
           or a SW library. */
-         nReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
+         uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
          break;
 
-
       default:
-         nReturn = QCBOR_ERR_BAD_OPT_TAG;
+         uReturn = QCBOR_ERR_BAD_OPT_TAG;
          goto Done;
    }
    pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
 
 Done:
-   return nReturn;
+   return uReturn;
 }
 
 
@@ -2481,8 +2486,8 @@
       /* Get the item */
       QCBORItem Item;
       uReturn = QCBORDecode_GetNext(pMe, &Item);
-      if(uReturn != QCBOR_SUCCESS) {
-         /* Got non-well-formed CBOR */
+      if(QCBORDecode_IsNotWellFormed(uReturn)) {
+         /* Got non-well-formed CBOR so map can't even be decoded. */
          goto Done;
       }
        
@@ -2533,7 +2538,7 @@
        to match the labels.
        */
       uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
-      if(uReturn) {
+      if(uReturn != QCBOR_SUCCESS) {
          goto Done;
       }
       
@@ -2549,8 +2554,8 @@
    DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
 
  Done2:
-    /* For all items not found, set the data type to QCBOR_TYPE_NONE */
-    for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
+   /* For all items not found, set the data type to QCBOR_TYPE_NONE */
+   for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
       if(!(uFoundItemBitMap & (0x01ULL << i))) {
          pItemArray[i].uDataType = QCBOR_TYPE_NONE;
       }
@@ -3215,6 +3220,91 @@
 
 
 
+
+
+static void ProcessEpochDate(QCBORDecodeContext *pMe,
+                             QCBORItem           *pItem,
+                             uint8_t              uTagRequirement,
+                             int64_t             *pnTime)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      // Already in error state, do nothing
+      return;
+   }
+
+   QCBORError uErr;
+
+   const TagSpecification TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
+   };
+
+   // TODO: this will give a unexpected type error instead of
+   // overflow error for QCBOR_TYPE_UINT64 because TagSpec
+   // only has three target types.
+   uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
+      uErr = DecodeDateEpoch(pItem);
+      if(uErr != QCBOR_SUCCESS) {
+         goto Done;
+      }
+   }
+
+   *pnTime = pItem->val.epochDate.nSeconds;
+
+Done:
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
+                             uint8_t             uTagRequirement,
+                             int64_t            *pnTime)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      // Already in error state, do nothing
+      return;
+   }
+
+   QCBORItem  Item;
+   pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
+
+   ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+void
+QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnTime)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+void
+QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t            *pnTime)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+
+
 void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
                                          TagSpecification    TagSpec,
                                          UsefulBufC         *pBstr)
@@ -3529,8 +3619,6 @@
 
 
 
-#include <math.h>
-
 
 static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
 {
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 2d53f4b..d882d99 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -2101,9 +2101,15 @@
    0xc0, // tag for string date
    0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string
 
+   0xc0, // tag for string date
+   0x00, // Wrong type for a string date
+
    0xc1, // tag for epoch date
    0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
 
+   0xc1,
+   0x62, 'h', 'i', // wrong type tagged
+
    // CBOR_TAG_B64
    0xc1, 0xcf, 0xd8, 0x22, // 0xee, // Epoch date with extra tags
    0x1a, 0x53, 0x72, 0x4E, 0x01,
@@ -2122,10 +2128,20 @@
    //0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large
 
    0xc1, // tag for epoch date
-   0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe // 9223372036854773760 largest supported
+   0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // 9223372036854773760 largest supported
+
+   0xc1, // tag for epoch date
+   0xfa, 0x7f, 0xc0, 0x00, 0x00, // Single-precision NaN
+
+   0xc1,
+   0xfb, 0x7f,  0xf0,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // +infinity
+
+   0xc1, // tag for epoch date
+   0xf9, 0xfc, 0x00, // -Infinity
 };
 
 
+
 // have to check float expected only to within an epsilon
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
 static int CHECK_EXPECTED_DOUBLE(double val, double expected) {
@@ -2142,69 +2158,79 @@
 int32_t DateParseTest()
 {
    QCBORDecodeContext DCtx;
-   QCBORItem Item;
-   QCBORError nCBORError;
+   QCBORItem          Item;
+   QCBORError         uError;
 
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput),
                     QCBOR_DECODE_MODE_NORMAL);
 
-   const uint64_t uTags[] = {15};
-   QCBORTagListIn TagList = {1, uTags};
-
-   QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList);
-
    // String date
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
+   if((uError = QCBORDecode_GetNext(&DCtx, &Item))) {
       return -1;
+   }
    if(Item.uDataType != QCBOR_TYPE_DATE_STRING ||
       UsefulBuf_Compare(Item.val.dateString, UsefulBuf_FromSZ("1985-04-12"))){
       return -2;
    }
 
-   // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
+   // Wrong type for a string date
+   uError = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uError != QCBOR_ERR_BAD_OPT_TAG) {
       return -3;
+   }
+
+   // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
+   if((uError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return -4;
+   }
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
       Item.val.epochDate.nSeconds != 1400000000 ||
       Item.val.epochDate.fSecondsFraction != 0 ) {
-      return -4;
+      return -5;
+   }
+
+   // Wrong type for an epoch date
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_OPT_TAG) {
+      return -6;
    }
 
    // Epoch date with extra CBOR_TAG_B64 tag that doesn't really mean anything
    // but want to be sure extra tag doesn't cause a problem
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return -5;
+   if((uError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return -7;
+   }
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
       Item.val.epochDate.nSeconds != 1400000001 ||
       Item.val.epochDate.fSecondsFraction != 0 ||
       !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_B64)) {
-      return -6;
+      return -8;
    }
 
    // Epoch date that is too large for our representation
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
-      return -7;
+      return -9;
    }
 
-   // Epoch date in float format with fractional seconds
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return -8;
+   // Epoch date in float format with fractional seconds
+   if((uError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return -10;
+   }
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
       Item.val.epochDate.nSeconds != 1 ||
       CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) {
-      return -9;
+      return -11;
    }
 
    // Epoch date float that is too large for our representation
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
-      return -10;
+      return -12;
    }
 
    // Epoch date double that is just slightly too large
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
-      return -11;
+      return -13;
    }
 
    // Largest double epoch date supported
@@ -2212,30 +2238,188 @@
        Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
        Item.val.epochDate.nSeconds != 9223372036854773760 ||
        Item.val.epochDate.nSeconds == 0) {
-       return -12;
+       return -14;
     }
+
+   // Nan
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
+      return -15;
+   }
+
+   // +Inifinity double-precision
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
+      return -16;
+   }
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   // -Inifinity half-precision
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
+      return -17;
+   }
 #else
-   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
-      return -80;
-   }
-   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
-      return -80;
-   }
-   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
-      return -80;
-   }
-   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
-      return -80;
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_HALF_PRECISION_DISABLED) {
+      return -18;
    }
 #endif
 
+#else
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -19;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -20;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -21;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -22;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -23;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -24;
+   }
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+      return -25;
+   }
+#else
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_HALF_PRECISION_DISABLED) {
+      return -26;
+   }
+#endif
 
-   // TODO: could use a few more tests with float, double, and half precsion
-   // and negative (but coverage is still pretty good)
+#endif
 
    return 0;
 }
 
+
+static uint8_t spDateTestInput2[] = {
+   0xbf,
+
+   0x05,
+   0xc1, // tag for epoch date
+   0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer
+
+   0x00,
+   0xc0, // tag for string date
+   0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string
+
+   0x01,
+   0xc1, // tag for epoch date
+   0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
+
+   // Untagged integer 0
+   0x08,
+   0x00,
+
+   // Utagged date string with string label y
+   0x61, 0x79,
+   0x6a, '2','0','8','5','-','0','4','-','1','2', // Date string
+
+   // Untagged -1000 with label z
+   0x61, 0x7a,
+   0x39, 0x03, 0xe7,
+
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+   0x07,
+   0xc1, // tag for epoch date
+   0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // 9223372036854773760 largest supported
+
+   // Untagged single-precision float with value 3.14 with string label x
+   0x61, 0x78,
+   0xFA, 0x40, 0x48, 0xF5, 0xC3,
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   // Untagged half-precision float with value -2
+   0x09,
+   0xF9, 0xC0, 0x00,
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+   0xff,
+};
+
+int32_t SpiffyDateDecodeTest()
+{
+   QCBORDecodeContext DC;
+   //QCBORItem Item;
+   QCBORError uError;
+   int64_t nEpochDate1, nEpochDate3, nEpochDate6;
+   UsefulBufC StringDate1, StringDate2;
+
+   QCBORDecode_Init(&DC,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput2),
+                    QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_EnterMap(&DC);
+   QCBORDecode_GetEpochDateInMapN(&DC, 5, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+   uError = QCBORDecode_GetAndResetError(&DC);
+   if(uError == QCBOR_SUCCESS) {
+      return -999;
+   }
+   QCBORDecode_GetEpochDateInMapN(&DC, 1, QCBOR_TAG_REQUIREMENT_MATCH_TAG, &nEpochDate1);
+   QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &StringDate1);
+   QCBORDecode_GetEpochDateInMapN(&DC, 8, QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate3);
+   QCBORDecode_GetDateStringInMapSZ(&DC, "y", QCBOR_TAG_REQUIREMENT_NO_TAG, &StringDate2);
+   QCBORDecode_GetEpochDateInMapSZ(&DC, "z", QCBOR_TAG_REQUIREMENT_NO_TAG, &nEpochDate6);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+   int64_t nEpochDate5, nEpochDate2;
+   QCBORDecode_GetEpochDateInMapN(&DC, 7, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate2);
+   QCBORDecode_GetEpochDateInMapSZ(&DC, "x", QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate5);
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   int64_t nEpochDate4;
+   QCBORDecode_GetEpochDateInMapN(&DC, 9, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate4);
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+   QCBORDecode_ExitMap(&DC);
+   uError = QCBORDecode_Finish(&DC);
+   if(uError) {
+      return 1;
+   }
+
+   if(nEpochDate1 != 1400000000) {
+      return 100;
+   }
+
+   if(nEpochDate3 != 0) {
+      return 102;
+   }
+
+   if(nEpochDate6 != -1000) {
+      return 105;
+   }
+
+   if(UsefulBuf_Compare(StringDate1, UsefulBuf_FromSZ("1985-04-12"))) {
+      return 106;
+   }
+
+   if(UsefulBuf_Compare(StringDate2, UsefulBuf_FromSZ("2085-04-12"))) {
+      return 107;
+   }
+
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+   if(nEpochDate2 != 9223372036854773760ULL) {
+      return 101;
+   }
+   if(nEpochDate5 != 3) {
+      return 104;
+   }
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   if(nEpochDate4 != -2) {
+      return 103;
+   }
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+   return 0;
+}
+
+
+
 // Really simple basic input for tagging test
 static uint8_t spOptTestInput[] = {
    0xd9, 0xd9, 0xf7, // CBOR magic number
@@ -4724,9 +4908,15 @@
    if(Item.uDataType != QCBOR_TYPE_DATE_STRING) {
       return 2;
    }
-   
+
    // Get a second item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uCBORError != QCBOR_ERR_BAD_OPT_TAG) {
+      return 66;
+   }
+
+   // Get a third item
+   uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_SUCCESS) {
       return 2;
    }
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 08f1759..d0ba252 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -161,12 +161,18 @@
 
 
 /*
- Thest the date types -- epoch and strings
+ Test the date types -- epoch and strings
  */
 int32_t DateParseTest(void);
 
 
 /*
+ Test spiffy date decoding functions
+ */
+int32_t SpiffyDateDecodeTest(void);
+
+
+/*
   Test optional tags like the CBOR magic number.
  */
 int32_t OptTagParseTest(void);
diff --git a/test/run_tests.c b/test/run_tests.c
index 0adccd4..be180a7 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -87,6 +87,7 @@
     TEST_ENTRY(BignumParseTest),
     TEST_ENTRY(OptTagParseTest),
     TEST_ENTRY(DateParseTest),
+    TEST_ENTRY(SpiffyDateDecodeTest),
     TEST_ENTRY(ShortBufferParseTest2),
     TEST_ENTRY(ShortBufferParseTest),
     TEST_ENTRY(ParseDeepArrayTest),