You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ja...@apache.org on 2018/07/09 14:52:43 UTC

[incubator-daffodil] 06/13: Fixed several bugs and added tests

This is an automated email from the ASF dual-hosted git repository.

jadams pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git

commit 322c3bfdd42a2c0a97f2cdf1738eeec6e5e20432
Author: Josh Adams <ja...@tresys.com>
AuthorDate: Wed Jun 13 16:11:55 2018 -0400

    Fixed several bugs and added tests
    
    Finally figured out how overpunched numbers worked in zoned decimal and
    updated conversion functions and tests to match.
---
 .../grammar/primitives/PrimitivesZoned.scala       |  12 +-
 .../org/apache/daffodil/util/DecimalUtils.scala    |  91 +++--
 .../apache/daffodil/util/TestDecimalUtils.scala    | 348 +++++++++++++++---
 .../unparsers/ConvertZonedNumberUnparser.scala     |  13 +-
 .../processors/parsers/ZonedTextParsers.scala      |  52 +--
 .../org/apache/daffodil/section13/zoned/zoned.tdml | 401 +++++++++++++++++++++
 .../daffodil/section13/zoned/TestZonedDebug.scala  |  39 ++
 .../daffodil/section13/zoned/TestZoned.scala       |  68 ++++
 8 files changed, 891 insertions(+), 133 deletions(-)

diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala
index 07acbd4..433f093 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala
@@ -90,12 +90,14 @@ abstract class ConvertZonedNumberPrim[S](e: ElementBase)
 
       e.primType match {
         case PrimType.Double | PrimType.Float => e.SDE("textZonedFormat='zoned' does not support Doubles/Floats")
-        case PrimType.UnsignedLong | PrimType.UnsignedInt | PrimType.UnsignedShort | PrimType.UnsignedByte if (e.textNumberCheckPolicy == TextNumberCheckPolicy.Lax) => {
-          if ((patternNoQuoted.charAt(0) != '+') || (patternNoQuoted.charAt(patternNoQuoted.length) != '+'))
-            e.SDE("textNumberPattern must have '+' at the beginning or the end of the pattern when textZonedFormat='zoned' and textNumberPolicy='lax' for unsigned numbers")
+        case PrimType.UnsignedLong | PrimType.UnsignedInt | PrimType.UnsignedShort | PrimType.UnsignedByte => {
+          if (e.textNumberCheckPolicy == TextNumberCheckPolicy.Lax) {
+            if ((patternNoQuoted.charAt(0) != '+') && (patternNoQuoted.charAt(patternNoQuoted.length - 1) != '+'))
+              e.SDE("textNumberPattern must have '+' at the beginning or the end of the pattern when textZonedFormat='zoned' and textNumberPolicy='lax' for unsigned numbers")
+          }
         }
         case _ => {
-          if ((patternNoQuoted.charAt(0) != '+') || (patternNoQuoted.charAt(patternNoQuoted.length) != '+'))
+          if ((patternNoQuoted.charAt(0) != '+') && (patternNoQuoted.charAt(patternNoQuoted.length - 1) != '+'))
             e.SDE("textNumberPattern must have '+' at the beginning or the end of the pattern when textZonedFormat='zoned' for signed numbers")
         }
       }
@@ -128,7 +130,7 @@ abstract class ConvertZonedNumberPrim[S](e: ElementBase)
 
   lazy val parser: Parser = new ConvertZonedNumberParser[S](helper, numFormatFactory, e.textZonedSignStyle, e.elementRuntimeData)
 
-  override lazy val unparser: Unparser = new ConvertZonedNumberUnparser[S](helper, e.textZonedSignStyle, e.elementRuntimeData)
+  override lazy val unparser: Unparser = new ConvertZonedNumberUnparser[S](helper, e.textNumberPattern, e.textZonedSignStyle, e.elementRuntimeData)
 }
 
 case class ConvertZonedIntegerPrim(e: ElementBase) extends ConvertZonedNumberPrim[JBigInt](e) {
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala
index fbff5d7..ce47c21 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala
@@ -335,78 +335,84 @@ object DecimalUtils {
     outArray
   }
 
-  def convertFromAsciiStandard(digit: Int): Int = {
+  def convertFromAsciiStandard(digit: Int): (Int, Boolean) = {
     if ((digit >= 48) && (digit <= 57)) // positive 0-9
-      return digit - 48
+      return (digit - 48, false)
     else if ((digit >= 112) && (digit <= 121)) // negative 0-9
-      return -(digit - 112)
+      return (digit - 112, true)
     else
-      return 0
+      throw new NumberFormatException("Invalid zoned digit: " + digit)
   }
 
-  def convertToAsciiStandard(digit: Char, positive: Boolean): Char = {
-    if (positive)
+  def convertToAsciiStandard(digit: Char, positive: Boolean, op: Boolean): Char = {
+    if (positive || !op)
       return digit
     else
       return (digit + 64).asInstanceOf[Char]
   }
 
-  def convertFromAsciiTranslatedEBCDIC(digit: Int): Int = {
-    if ((digit == 123) || (digit == 125))
-      return 0
+  def convertFromAsciiTranslatedEBCDIC(digit: Int): (Int, Boolean) = {
+    if (digit == 123)
+      return (0, false)
+    else if (digit == 125)
+      return (0, true)
     else if ((digit >= 65) && (digit <= 73)) // positive 1-9
-      return (digit - 64)
+      return (digit - 64, false)
     else if ((digit >= 74) && (digit <= 82)) // negative 1-9
-      return -(digit - 73)
+      return (digit - 73, true)
+    else if ((digit >= 48) && (digit <= 57))
+      return (digit - 48, false) // non-overpunched digit
     else
-      return 0
+      throw new NumberFormatException("Invalid zoned digit: " + digit)
   }
 
-  def convertToAsciiTranslatedEBCDIC(digit: Char, positive: Boolean): Char = {
-    val result = positive match {
-      case true => {
+  def convertToAsciiTranslatedEBCDIC(digit: Char, positive: Boolean, op: Boolean): Char = {
+    val result = (positive, op) match {
+      case (true, true) => { // Overpunch character with positive sign
         if (digit == '0')
           123
         else
           digit + 16
       }
-      case false => {
+      case (false, true) => { // Overpunch character with negative sign
         if (digit == '0')
           125
         else
           digit + 25
       }
+      case _ => digit
     }
 
     return result.asInstanceOf[Char]
   }
 
-  def convertFromAsciiCARealiaModified(digit: Int): Int = {
+  def convertFromAsciiCARealiaModified(digit: Int): (Int, Boolean) = {
     if ((digit >= 48) && (digit <= 57)) // positive 0-9
-      return digit - 48
+      return (digit - 48, false)
     else if ((digit >= 32) && (digit <= 41)) // negative 0-9
-      return -(digit - 32)
-    else return 0
+      return (digit - 32, true)
+    else
+      throw new NumberFormatException("Invalid zoned digit: " + digit)
   }
 
-  def convertToAsciiCARealiaModified(digit: Char, positive: Boolean): Char = {
-    if (positive)
+  def convertToAsciiCARealiaModified(digit: Char, positive: Boolean, op: Boolean): Char = {
+    if (positive || !op)
       return digit
     else
       return (digit - 16).asInstanceOf[Char]
   }
 
-  def convertFromAsciiTandemModified(digit: Int): Int = {
+  def convertFromAsciiTandemModified(digit: Int): (Int, Boolean) = {
     if ((digit >= 48) && (digit <= 57)) // positive 0-9
-      return digit - 48
+      return (digit - 48, false)
     else if ((digit >= 128) && (digit <= 137)) // negative 0-9
-      return -(digit - 128)
+      return (digit - 128, true)
     else
-      return 0
+      throw new NumberFormatException("Invalid zoned digit: " + digit)
   }
 
-  def convertToAsciiTandemModified(digit: Char, positive: Boolean): Char = {
-    if (positive)
+  def convertToAsciiTandemModified(digit: Char, positive: Boolean, op: Boolean): Char = {
+    if (positive || !op)
       return digit
     else
       return (digit + 80).asInstanceOf[Char]
@@ -417,38 +423,49 @@ object DecimalUtils {
     var negative = false
 
     for (char <- num.chars().toArray) {
-      val digit = zonedStyle match {
+      val (digit, opneg) = zonedStyle match {
         case TextZonedSignStyle.AsciiStandard => convertFromAsciiStandard(char)
         case TextZonedSignStyle.AsciiTranslatedEBCDIC => convertFromAsciiTranslatedEBCDIC(char)
         case TextZonedSignStyle.AsciiCARealiaModified => convertFromAsciiCARealiaModified(char)
         case TextZonedSignStyle.AsciiTandemModified => convertFromAsciiTandemModified(char)
       }
 
-      if ((digit < 0) && !negative) {
+      if (opneg && !negative) {
         negative = true
         decodedValue.insert(0, '-')
       }
 
-      decodedValue.append(java.lang.Math.abs(digit))
+      decodedValue.append(digit)
     }
 
     return decodedValue.toString
   }
 
-  def zonedFromNumber(num: String, zonedStyle: TextZonedSignStyle): String = {
+  object OverpunchLocation extends Enumeration {
+    type OverpunchLocation = Value
+    val Start, End, None = Value
+  }
+
+  def zonedFromNumber(num: String, zonedStyle: TextZonedSignStyle, opl: OverpunchLocation.Value): String = {
     val positive = (num.charAt(0) != '-')
     val inChars = positive match {
       case true => num.toCharArray
       case false => num.substring(1).toCharArray
     }
+    val opindex = opl match {
+      case OverpunchLocation.Start => 0
+      case OverpunchLocation.End => inChars.length - 1
+      case _ => -1
+    }
     val encodedValue = new StringBuilder()
 
-    for (char <- inChars) {
+    for (i <- 0 to inChars.length - 1) {
+      val op = (i == opindex)
       val digit = zonedStyle match {
-        case TextZonedSignStyle.AsciiStandard => convertToAsciiStandard(char, positive)
-        case TextZonedSignStyle.AsciiTranslatedEBCDIC => convertToAsciiTranslatedEBCDIC(char, positive)
-        case TextZonedSignStyle.AsciiCARealiaModified => convertToAsciiCARealiaModified(char, positive)
-        case TextZonedSignStyle.AsciiTandemModified => convertToAsciiTandemModified(char, positive)
+        case TextZonedSignStyle.AsciiStandard => convertToAsciiStandard(inChars(i), positive, op)
+        case TextZonedSignStyle.AsciiTranslatedEBCDIC => convertToAsciiTranslatedEBCDIC(inChars(i), positive, op)
+        case TextZonedSignStyle.AsciiCARealiaModified => convertToAsciiCARealiaModified(inChars(i), positive, op)
+        case TextZonedSignStyle.AsciiTandemModified => convertToAsciiTandemModified(inChars(i), positive, op)
       }
 
       encodedValue.append(digit)
diff --git a/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala b/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala
index e2c3980..85a9554 100644
--- a/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala
+++ b/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala
@@ -1254,210 +1254,472 @@ class TestDecimalUtils {
     val num = "1"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "1")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiStandardPos2() {
     val num = "12"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "12")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiStandardPos3() {
     val num = "123"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "123")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.None), num)
   }
 
   @Test def zonedIntAsciiStandardPos4() {
     val num = "1234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "1234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiStandardPos5() {
     val num = "000000000001234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "000000000001234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), "000000000001234567890")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "000000000001234567890")
   }
 
   @Test def zonedIntAsciiStandardNeg1() {
     val num = "q"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "-1")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiStandardNeg2() {
-    val num = "qr"
+    val num = "1r"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "-12")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiStandardNeg3() {
-    val num = "qrs"
+    val num = "q23"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "-123")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiStandardNeg4() {
-    val num = "qrstuvwxyp"
+    val num = "123456789p"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "-1234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiStandardNeg5() {
-    val num = "pppppppppppqrstuvwxyp"
+    val num = "p00000000001234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard)
     assertEquals(result, "-000000000001234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
   }
 
+  @Test def zonedIntAsciiTranslatedEBCDICPos1() {
+    val num = "A"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "1")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICPos2() {
+    val num = "1B"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "12")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICPos3() {
+    val num = "123"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "123")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICPos4() {
+    val num = "A234567890"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "1234567890")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICPos5() {
+    val num = "00000000000123456789{"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "000000000001234567890")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICNeg1() {
+    val num = "J"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "-1")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICNeg2() {
+    val num = "1K"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "-12")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICNeg3() {
+    val num = "J23"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "-123")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICNeg4() {
+    val num = "123456789}"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "-1234567890")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICNeg5() {
+    val num = "}00000000001234567890"
+    val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC)
+    assertEquals(result, "-000000000001234567890")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+  }
+
+
   @Test def zonedIntAsciiCARealiaModifiedPos1() {
     val num = "1"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "1")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedPos2() {
     val num = "12"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "12")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedPos3() {
     val num = "123"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "123")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.None), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedPos4() {
     val num = "1234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "1234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedPos5() {
     val num = "000000000001234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "000000000001234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), "000000000001234567890")
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedNeg1() {
     val num = "!"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "-1")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedNeg2() {
-    val num = "!\""
+    val num = "1\""
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "-12")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedNeg3() {
-    val num = "!\"#"
+    val num = "!23"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "-123")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedNeg4() {
-    val num = "!\"#$%&'() "
+    val num = "123456789 "
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "-1234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiCARealiaModifiedNeg5() {
-    val num = "           !\"#$%&'() "
+    val num = " 00000000001234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified)
     assertEquals(result, "-000000000001234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedPos1() {
     val num = "1"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "1")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedPos2() {
     val num = "12"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "12")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedPos3() {
     val num = "123"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "123")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.None), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedPos4() {
     val num = "1234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "1234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedPos5() {
     val num = "000000000001234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "000000000001234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedNeg1() {
     val num = ""
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "-1")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedNeg2() {
-    val num = "‚"
+    val num = "1‚"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "-12")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedNeg3() {
-    val num = "‚ƒ"
+    val num = "23"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "-123")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedNeg4() {
-    val num = "‚ƒ„…†‡ˆ‰€"
+    val num = "123456789€"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "-1234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
   }
 
   @Test def zonedIntAsciiTandemModifiedNeg5() {
-    val num = "€€€€€€€€€€€‚ƒ„…†‡ˆ‰€"
+    val num = "€00000000001234567890"
     val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified)
     assertEquals(result, "-000000000001234567890")
-    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified), num)
+    assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
+  }
+
+  @Test def zonedIntAsciiStandardAllDigits() {
+    assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiStandard), "0")
+    assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "0")
+    assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiStandard), "1")
+    assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "1")
+    assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiStandard), "2")
+    assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "2")
+    assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiStandard), "3")
+    assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "3")
+    assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiStandard), "4")
+    assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "4")
+    assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiStandard), "5")
+    assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "5")
+    assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiStandard), "6")
+    assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "6")
+    assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiStandard), "7")
+    assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "7")
+    assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiStandard), "8")
+    assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "8")
+    assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiStandard), "9")
+    assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "9")
+    assertEquals(zonedToNumber("1p", TextZonedSignStyle.AsciiStandard), "-10")
+    assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), "1p")
+    assertEquals(zonedToNumber("q", TextZonedSignStyle.AsciiStandard), "-1")
+    assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "q")
+    assertEquals(zonedToNumber("r", TextZonedSignStyle.AsciiStandard), "-2")
+    assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "r")
+    assertEquals(zonedToNumber("s", TextZonedSignStyle.AsciiStandard), "-3")
+    assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "s")
+    assertEquals(zonedToNumber("t", TextZonedSignStyle.AsciiStandard), "-4")
+    assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "t")
+    assertEquals(zonedToNumber("u", TextZonedSignStyle.AsciiStandard), "-5")
+    assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "u")
+    assertEquals(zonedToNumber("v", TextZonedSignStyle.AsciiStandard), "-6")
+    assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "v")
+    assertEquals(zonedToNumber("w", TextZonedSignStyle.AsciiStandard), "-7")
+    assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "w")
+    assertEquals(zonedToNumber("x", TextZonedSignStyle.AsciiStandard), "-8")
+    assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "x")
+    assertEquals(zonedToNumber("y", TextZonedSignStyle.AsciiStandard), "-9")
+    assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "y")
+  }
+
+  @Test def zonedIntAsciiTranslatedEBCDICAllDigits() {
+    assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiTranslatedEBCDIC), "0")
+    assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "0")
+    assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiTranslatedEBCDIC), "1")
+    assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "1")
+    assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiTranslatedEBCDIC), "2")
+    assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "2")
+    assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiTranslatedEBCDIC), "3")
+    assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "3")
+    assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiTranslatedEBCDIC), "4")
+    assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "4")
+    assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiTranslatedEBCDIC), "5")
+    assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "5")
+    assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiTranslatedEBCDIC), "6")
+    assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "6")
+    assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiTranslatedEBCDIC), "7")
+    assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "7")
+    assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiTranslatedEBCDIC), "8")
+    assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "8")
+    assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiTranslatedEBCDIC), "9")
+    assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "9")
+    assertEquals(zonedToNumber("{", TextZonedSignStyle.AsciiTranslatedEBCDIC), "0")
+    assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "{")
+    assertEquals(zonedToNumber("A", TextZonedSignStyle.AsciiTranslatedEBCDIC), "1")
+    assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "A")
+    assertEquals(zonedToNumber("B", TextZonedSignStyle.AsciiTranslatedEBCDIC), "2")
+    assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "B")
+    assertEquals(zonedToNumber("C", TextZonedSignStyle.AsciiTranslatedEBCDIC), "3")
+    assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "C")
+    assertEquals(zonedToNumber("D", TextZonedSignStyle.AsciiTranslatedEBCDIC), "4")
+    assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "D")
+    assertEquals(zonedToNumber("E", TextZonedSignStyle.AsciiTranslatedEBCDIC), "5")
+    assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "E")
+    assertEquals(zonedToNumber("F", TextZonedSignStyle.AsciiTranslatedEBCDIC), "6")
+    assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "F")
+    assertEquals(zonedToNumber("G", TextZonedSignStyle.AsciiTranslatedEBCDIC), "7")
+    assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "G")
+    assertEquals(zonedToNumber("H", TextZonedSignStyle.AsciiTranslatedEBCDIC), "8")
+    assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "H")
+    assertEquals(zonedToNumber("I", TextZonedSignStyle.AsciiTranslatedEBCDIC), "9")
+    assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "I")
+    assertEquals(zonedToNumber("1}", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-10")
+    assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), "1}")
+    assertEquals(zonedToNumber("J", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-1")
+    assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "J")
+    assertEquals(zonedToNumber("K", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-2")
+    assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "K")
+    assertEquals(zonedToNumber("L", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-3")
+    assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "L")
+    assertEquals(zonedToNumber("M", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-4")
+    assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "M")
+    assertEquals(zonedToNumber("N", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-5")
+    assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "N")
+    assertEquals(zonedToNumber("O", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-6")
+    assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "O")
+    assertEquals(zonedToNumber("P", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-7")
+    assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "P")
+    assertEquals(zonedToNumber("Q", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-8")
+    assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "Q")
+    assertEquals(zonedToNumber("R", TextZonedSignStyle.AsciiTranslatedEBCDIC), "-9")
+    assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "R")
+  }
+
+  @Test def zonedIntAsciiCARealiaModifiedAllDigits() {
+    assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiCARealiaModified), "0")
+    assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "0")
+    assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiCARealiaModified), "1")
+    assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "1")
+    assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiCARealiaModified), "2")
+    assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "2")
+    assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiCARealiaModified), "3")
+    assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "3")
+    assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiCARealiaModified), "4")
+    assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "4")
+    assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiCARealiaModified), "5")
+    assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "5")
+    assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiCARealiaModified), "6")
+    assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "6")
+    assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiCARealiaModified), "7")
+    assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "7")
+    assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiCARealiaModified), "8")
+    assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "8")
+    assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiCARealiaModified), "9")
+    assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "9")
+    assertEquals(zonedToNumber("1 ", TextZonedSignStyle.AsciiCARealiaModified), "-10")
+    assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), "1 ")
+    assertEquals(zonedToNumber("!", TextZonedSignStyle.AsciiCARealiaModified), "-1")
+    assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "!")
+    assertEquals(zonedToNumber("\"", TextZonedSignStyle.AsciiCARealiaModified), "-2")
+    assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "\"")
+    assertEquals(zonedToNumber("#", TextZonedSignStyle.AsciiCARealiaModified), "-3")
+    assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "#")
+    assertEquals(zonedToNumber("$", TextZonedSignStyle.AsciiCARealiaModified), "-4")
+    assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "$")
+    assertEquals(zonedToNumber("%", TextZonedSignStyle.AsciiCARealiaModified), "-5")
+    assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "%")
+    assertEquals(zonedToNumber("&", TextZonedSignStyle.AsciiCARealiaModified), "-6")
+    assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "&")
+    assertEquals(zonedToNumber("'", TextZonedSignStyle.AsciiCARealiaModified), "-7")
+    assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "'")
+    assertEquals(zonedToNumber("(", TextZonedSignStyle.AsciiCARealiaModified), "-8")
+    assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "(")
+    assertEquals(zonedToNumber(")", TextZonedSignStyle.AsciiCARealiaModified), "-9")
+    assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), ")")
+  }
+
+  @Test def zonedIntAsciiTandemModifiedAllDigits() {
+    assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiTandemModified), "0")
+    assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "0")
+    assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiTandemModified), "1")
+    assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "1")
+    assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiTandemModified), "2")
+    assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "2")
+    assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiTandemModified), "3")
+    assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "3")
+    assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiTandemModified), "4")
+    assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "4")
+    assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiTandemModified), "5")
+    assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "5")
+    assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiTandemModified), "6")
+    assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "6")
+    assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiTandemModified), "7")
+    assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "7")
+    assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiTandemModified), "8")
+    assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "8")
+    assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiTandemModified), "9")
+    assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "9")
+    assertEquals(zonedToNumber("1€", TextZonedSignStyle.AsciiTandemModified), "-10")
+    assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), "1€")
+    assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified), "-1")
+    assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+    assertEquals(zonedToNumber("‚", TextZonedSignStyle.AsciiTandemModified), "-2")
+    assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "‚")
+    assertEquals(zonedToNumber("ƒ", TextZonedSignStyle.AsciiTandemModified), "-3")
+    assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "ƒ")
+    assertEquals(zonedToNumber("„", TextZonedSignStyle.AsciiTandemModified), "-4")
+    assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "„")
+    assertEquals(zonedToNumber("…", TextZonedSignStyle.AsciiTandemModified), "-5")
+    assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "…")
+    assertEquals(zonedToNumber("†", TextZonedSignStyle.AsciiTandemModified), "-6")
+    assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "†")
+    assertEquals(zonedToNumber("‡", TextZonedSignStyle.AsciiTandemModified), "-7")
+    assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "‡")
+    assertEquals(zonedToNumber("ˆ", TextZonedSignStyle.AsciiTandemModified), "-8")
+    assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "ˆ")
+    assertEquals(zonedToNumber("‰", TextZonedSignStyle.AsciiTandemModified), "-9")
+    assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "‰")
   }
-
 }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala
index bfa31d4..efcfa01 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala
@@ -20,6 +20,7 @@ package org.apache.daffodil.processors.unparsers
 import org.apache.daffodil.schema.annotation.props.gen.TextZonedSignStyle
 import org.apache.daffodil.processors._
 import org.apache.daffodil.util.DecimalUtils
+import org.apache.daffodil.util.DecimalUtils.OverpunchLocation
 import org.apache.daffodil.processors.parsers.ConvertZonedNumberParserUnparserHelperBase
 
 case class ConvertZonedCombinatorUnparser(
@@ -43,6 +44,7 @@ case class ConvertZonedCombinatorUnparser(
 
 case class ConvertZonedNumberUnparser[S](
   helper: ConvertZonedNumberParserUnparserHelperBase[S],
+  pattern: String,
   zonedSignStyle: TextZonedSignStyle,
   override val context: ElementRuntimeData)
   extends PrimUnparser
@@ -63,7 +65,16 @@ case class ConvertZonedNumberUnparser[S](
     // if we find this is not the case. Want something akin to:
     // Assert.invariant(value.isInstanceOf[S])
 
-    val strRep = DecimalUtils.zonedFromNumber(value, zonedSignStyle)
+    val opindex = pattern.indexOf('+')
+    val opl = {
+      if (opindex == 0)
+        OverpunchLocation.Start
+      else if (opindex == pattern.length - 1)
+        OverpunchLocation.End
+      else
+        OverpunchLocation.None
+    }
+    val strRep = DecimalUtils.zonedFromNumber(value, zonedSignStyle, opl)
 
     node.overwriteDataValue(strRep)
   }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala
index ceaac9a..d64a55d 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala
@@ -25,13 +25,11 @@ import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.DecimalUtils
 import java.text.ParsePosition
 import com.ibm.icu.text.DecimalFormat
-import com.ibm.icu.text.DecimalFormatSymbols
 import org.apache.daffodil.util.MaybeDouble
 import org.apache.daffodil.util.MaybeDouble
 import java.lang.{ Number => JNumber }
 import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt }
 import org.apache.daffodil.infoset.DISimple
-import org.apache.daffodil.processors.Dynamic
 import org.apache.daffodil.processors.ElementRuntimeData
 import org.apache.daffodil.processors.ParseOrUnparseState
 import org.apache.daffodil.processors.Success
@@ -78,6 +76,7 @@ case class ConvertZonedNumberParser[S](
       return
     }
 
+    var checkLength = str.length
     // because of the way the zero rep regular expressions are generated, they
     // will match either all or none of 'str', never part of it. Thus,
     // findFirstIn() either matches and it's a zero rep, or it doesn't and it's
@@ -87,6 +86,8 @@ case class ConvertZonedNumberParser[S](
       val pos = new ParsePosition(0)
       val num = try {
         val decodedNum = DecimalUtils.zonedToNumber(str, zonedSignStyle)
+        if (decodedNum(0) == '-')
+          checkLength = checkLength + 1
         df.get.parse(decodedNum, pos)
       } catch {
         case s: scala.util.control.ControlThrowable => throw s
@@ -100,7 +101,7 @@ case class ConvertZonedNumberParser[S](
 
       // Verify that what was parsed was what was passed exactly in byte count.
       // Use pos to verify all characters consumed & check for errors!
-      if (num == null || pos.getIndex != str.length) {
+      if (num == null || pos.getIndex != checkLength) {
         PE(start, "Convert to %s (for xs:%s): Unable to parse '%s' (using up all characters).",
           helper.prettyType, helper.xsdType, str)
         return
@@ -394,9 +395,7 @@ abstract class ZonedFormatFactoryBase[S](parserHelper: ConvertZonedNumberParserU
     roundingMode: Maybe[TextNumberRoundingMode],
     roundingIncrement: MaybeDouble) = {
 
-    val dfs = new DecimalFormatSymbols()
-
-    val df = new DecimalFormat(pattern, dfs)
+    val df = new DecimalFormat(pattern.replace("+", ""))
 
     val cp = checkPolicy match {
       case TextNumberCheckPolicy.Strict => true
@@ -445,10 +444,6 @@ abstract class ZonedFormatFactoryBase[S](parserHelper: ConvertZonedNumberParserU
 
 }
 
-//
-// TODO: Complexity - why do we need both Static and Dynamic variants of this?
-// CachedDynamic hides this distinction (or should), as does CompiledExpression underneath that.
-
 class ZonedFormatFactoryStatic[S](context: ThrowsSDE,
   parserHelper: ConvertZonedNumberParserUnparserHelperBase[S],
   checkPolicy: TextNumberCheckPolicy,
@@ -478,40 +473,3 @@ class ZonedFormatFactoryStatic[S](context: ThrowsSDE,
     numFormat
   }
 }
-
-class ZonedFormatFactoryDynamic[S](staticContext: ThrowsSDE,
-  parserHelper: ConvertZonedNumberParserUnparserHelperBase[S],
-  checkPolicy: TextNumberCheckPolicy,
-  pattern: String,
-  rounding: TextNumberRounding,
-  roundingMode: Maybe[TextNumberRoundingMode],
-  roundingIncrement: MaybeDouble)
-  extends ZonedFormatFactoryBase[S](parserHelper)
-  with Dynamic {
-
-  checkUnique(staticContext)
-
-  val roundingInc = if (roundingIncrement.isEmpty) MaybeDouble.Nope else MaybeDouble { getRoundingIncrement(roundingIncrement.value, staticContext) }
-
-  def getNumFormat(state: ParseOrUnparseState): ThreadLocal[DecimalFormat] = {
-
-    checkUnique(state)
-
-    val generatedNumFormat =
-      generateNumFormat(
-        checkPolicy,
-        pattern,
-        rounding,
-        roundingMode,
-        roundingInc)
-
-    val numFormat = new ThreadLocal[DecimalFormat] {
-      override def initialValue() = {
-        generatedNumFormat
-      }
-    }
-
-    numFormat
-  }
-
-}
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section13/zoned/zoned.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section13/zoned/zoned.tdml
new file mode 100644
index 0000000..326459e
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section13/zoned/zoned.tdml
@@ -0,0 +1,401 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<tdml:testSuite suiteName="zoned"
+  description="Zoned Number Properties" xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ct="http://w3.ibm.com/xmlns/dfdl/ctInfoset"
+  xmlns:ex="http://example.com" xmlns="http://example.com" xmlns:tns="http://example.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  defaultRoundTrip="true">
+
+  <tdml:defineSchema name="s1">
+    <dfdl:format ref="ex:GeneralFormat" lengthKind="explicit" encoding="ISO-8859-1" occursCountKind="implicit"
+      textNumberCheckPolicy="strict" textNumberPadCharacter="0" textNumberJustification="right" textNumberRep="zoned"
+      textZonedSignStyle="asciiStandard"
+    lengthUnits="characters"/>
+
+    <xs:element name="int01" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="+00@00" />
+    <xs:element name="int02" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="0000" />
+    <xs:element name="uint03" type="xs:unsignedInt" dfdl:length="4" dfdl:textNumberPattern="0000" dfdl:textNumberCheckPolicy="lax"/>
+    <xs:element name="int04" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="+00;00" />
+    <xs:element name="float01" type="xs:float" dfdl:length="4" dfdl:textNumberPattern="+00;00" />
+    <xs:element name="double01" type="xs:double" dfdl:length="4" dfdl:textNumberPattern="+00;00" />
+
+
+    <xs:element name="standard01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" />
+    <xs:element name="standard02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" />
+    <xs:element name="standard03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" />
+
+    <xs:element name="trans01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" dfdl:textZonedSignStyle="asciiTranslatedEBCDIC" />
+    <xs:element name="trans02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" dfdl:textZonedSignStyle="asciiTranslatedEBCDIC" />
+    <xs:element name="trans03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" dfdl:textZonedSignStyle="asciiTranslatedEBCDIC" />
+<xs:element name="mod01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" dfdl:textZonedSignStyle="asciiCARealiaModified" />
+    <xs:element name="mod02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" dfdl:textZonedSignStyle="asciiCARealiaModified" />
+    <xs:element name="mod03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" dfdl:textZonedSignStyle="asciiCARealiaModified" />
+
+    <xs:element name="tmod01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" dfdl:textZonedSignStyle="asciiTandemModified" />
+    <xs:element name="tmod02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" dfdl:textZonedSignStyle="asciiTandemModified" />
+    <xs:element name="tmod03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" dfdl:textZonedSignStyle="asciiTandemModified" />
+  </tdml:defineSchema>
+  
+  <tdml:parserTestCase name="zoned_textNumberPattern_fail01" root="int01" model="s1"
+    description="This test should fail because '@' is not allowed to appear in the textNumberPattern for zoned numbers">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1988</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>The '@' symbol may not be used</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="zoned_textNumberPattern_fail02" root="int02" model="s1"
+    description="This test should fail because '+' must be the first or last character in the textNumberPattern when using zoned numbers with signed types">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1988</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>textNumberPattern must have '+' at the beginning</tdml:error>
+      <tdml:error>for signed numbers</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="zoned_textNumberPattern_fail03" root="uint03" model="s1"
+    description="This test should fail because '+' must be the first or last character in the textNumberPattern when using zoned numbers and textNumberCheckPolicy=strict">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1988</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>textNumberPattern must have '+' at the beginning</tdml:error>
+      <tdml:error>for unsigned numbers</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="zoned_textNumberPattern_fail04" root="int04" model="s1"
+    description="This test should fail because negative number patterns may not be used with zoned numbers">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1988</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>Negative patterns may not be used</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="zoned_float_fail01" root="float01" model="s1"
+    description="This test should fail because floats are not supported with zoned decimal">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1988</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>Zoned not supported for float and double</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="zoned_double_fail01" root="double01" model="s1"
+    description="This test should fail because doubles are not supported with zoned decimal">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1988</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>Zoned not supported for float and double</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedStandard01" root="standard01" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiStandard">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <standard01>1234567890</standard01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedStandard02" root="standard01" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiStandard with overpunch on first char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">q234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <standard01>-1234567890</standard01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedStandard03" root="standard01" model="s1"
+    description="This test should fail as 'z' is not a valid digit in zoned AsciiStandard">
+
+    <tdml:document>
+      <tdml:documentPart type="text">z234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedStandard04" root="standard02" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiStandard with no overpunch char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <standard02>1234567890</standard02>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedStandard05" root="standard03" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiStandard with overpunch on last char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">123456789p</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <standard03>-1234567890</standard03>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTranslatedEBCDIC01" root="trans01" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiTranslatedEBCDIC">
+
+    <tdml:document>
+      <tdml:documentPart type="text">A234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <trans01>1234567890</trans01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTranslatedEBCDIC02" root="trans01" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiTranslatedEBCDIC with overpunch on first char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">J234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <trans01>-1234567890</trans01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTranslatedEBCDIC03" root="trans01" model="s1"
+    description="This test should fail as 'z' is not a valid digit in zoned AsciiTranslatedEBCDIC">
+
+    <tdml:document>
+      <tdml:documentPart type="text">z234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTranslatedEBCDIC04" root="trans02" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiTranslatedEBCDIC with no overpunch char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <trans02>1234567890</trans02>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTranslatedEBCDIC05" root="trans03" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiTranslatedEBCDIC with overpunch on last char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">123456789}</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <trans03>-1234567890</trans03>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedCARealiaModified01" root="mod01" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiCARealiaModified">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <mod01>1234567890</mod01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedCARealiaModified02" root="mod01" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiCARealiaModified with overpunch on first char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">!234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <mod01>-1234567890</mod01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedCARealiaModified03" root="mod01" model="s1"
+    description="This test should fail as 'z' is not a valid digit in zoned AsciiCARealiaModified">
+
+    <tdml:document>
+      <tdml:documentPart type="text">z234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedCARealiaModified04" root="mod02" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiCARealiaModified with no overpunch char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <mod02>1234567890</mod02>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedCARealiaModified05" root="mod03" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiCARealiaModified with overpunch on last char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">123456789 </tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <mod03>-1234567890</mod03>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTandemModified01" root="tmod01" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiTandemModified">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <tmod01>1234567890</tmod01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTandemModified02" root="tmod01" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiTandemModified with overpunch on first char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">&#x81;234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <tmod01>-1234567890</tmod01>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTandemModified03" root="tmod01" model="s1"
+    description="This test should fail as 'z' is not a valid digit in zoned AsciiTandemModified">
+
+    <tdml:document>
+      <tdml:documentPart type="text">z234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:errors>
+      <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+    </tdml:errors>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTandemModified04" root="tmod02" model="s1"
+    description="Test of a positive number with zonedSignStyle=asciiTandemModified with no overpunch char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">1234567890</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <tmod02>1234567890</tmod02>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="ZonedTandemModified05" root="tmod03" model="s1"
+    description="Test of a negative number with zonedSignStyle=asciiTandemModified with overpunch on last char">
+
+    <tdml:document>
+      <tdml:documentPart type="text">123456789&#x80;</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <tmod03>-1234567890</tmod03>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/scala-debug/org/apache/daffodil/section13/zoned/TestZonedDebug.scala b/daffodil-test/src/test/scala-debug/org/apache/daffodil/section13/zoned/TestZonedDebug.scala
new file mode 100644
index 0000000..bdd7fbc
--- /dev/null
+++ b/daffodil-test/src/test/scala-debug/org/apache/daffodil/section13/zoned/TestZonedDebug.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.section13.zoned
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestZoned {
+  val testDir = "/org/apache/daffodil/section13/zoned/"
+  lazy val runner = Runner(testDir, "zoned.tdml")
+
+  @AfterClass def shutdown(): Unit = {
+    runner.reset
+  }
+
+}
+
+class TestZoned {
+  import TestZoned._
+
+  @Test def testZonedTandemModified02(): Unit = { runner.trace.runOneTest("ZonedTandemModified02") }
+  @Test def testZonedTandemModified05(): Unit = { runner.trace.runOneTest("ZonedTandemModified05") }
+}
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section13/zoned/TestZoned.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section13/zoned/TestZoned.scala
new file mode 100644
index 0000000..4c95029
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section13/zoned/TestZoned.scala
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.section13.zoned
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestZoned {
+  val testDir = "/org/apache/daffodil/section13/zoned/"
+  lazy val runner = Runner(testDir, "zoned.tdml")
+
+  @AfterClass def shutdown(): Unit = {
+    runner.reset
+  }
+
+}
+
+class TestZoned {
+  import TestZoned._
+
+  @Test def testZonedPatternFail01(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail01") }
+  @Test def testZonedPatternFail02(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail02") }
+  @Test def testZonedPatternFail03(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail03") }
+  @Test def testZonedPatternFail04(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail04") }
+  @Test def testZonedFloatFail01(): Unit = { runner.runOneTest("zoned_float_fail01") }
+  @Test def testZonedDoubleFail01(): Unit = { runner.runOneTest("zoned_double_fail01") }
+  //TODO: @Test def testZonedEncodingFail01(): Unit = { runner.runOneTest("zoned_encoding_fail01") }
+
+  @Test def testZonedStandard01(): Unit = { runner.trace.runOneTest("ZonedStandard01") }
+  @Test def testZonedStandard02(): Unit = { runner.trace.runOneTest("ZonedStandard02") }
+  @Test def testZonedStandard03(): Unit = { runner.trace.runOneTest("ZonedStandard03") }
+  @Test def testZonedStandard04(): Unit = { runner.trace.runOneTest("ZonedStandard04") }
+  @Test def testZonedStandard05(): Unit = { runner.trace.runOneTest("ZonedStandard05") }
+
+  @Test def testZonedTranslatedEBCDIC01(): Unit = { runner.trace.runOneTest("ZonedTranslatedEBCDIC01") }
+  @Test def testZonedTranslatedEBCDIC02(): Unit = { runner.trace.runOneTest("ZonedTranslatedEBCDIC02") }
+  @Test def testZonedTranslatedEBCDIC03(): Unit = { runner.trace.runOneTest("ZonedTranslatedEBCDIC03") }
+  @Test def testZonedTranslatedEBCDIC04(): Unit = { runner.trace.runOneTest("ZonedTranslatedEBCDIC04") }
+  @Test def testZonedTranslatedEBCDIC05(): Unit = { runner.trace.runOneTest("ZonedTranslatedEBCDIC05") }
+
+  @Test def testZonedCARealiaModified01(): Unit = { runner.trace.runOneTest("ZonedCARealiaModified01") }
+  @Test def testZonedCARealiaModified02(): Unit = { runner.trace.runOneTest("ZonedCARealiaModified02") }
+  @Test def testZonedCARealiaModified03(): Unit = { runner.trace.runOneTest("ZonedCARealiaModified03") }
+  @Test def testZonedCARealiaModified04(): Unit = { runner.trace.runOneTest("ZonedCARealiaModified04") }
+  @Test def testZonedCARealiaModified05(): Unit = { runner.trace.runOneTest("ZonedCARealiaModified05") }
+
+  @Test def testZonedTandemModified01(): Unit = { runner.trace.runOneTest("ZonedTandemModified01") }
+  //@Test def testZonedTandemModified02(): Unit = { runner.trace.runOneTest("ZonedTandemModified02") }
+  @Test def testZonedTandemModified03(): Unit = { runner.trace.runOneTest("ZonedTandemModified03") }
+  @Test def testZonedTandemModified04(): Unit = { runner.trace.runOneTest("ZonedTandemModified04") }
+  //@Test def testZonedTandemModified05(): Unit = { runner.trace.runOneTest("ZonedTandemModified05") }
+}