views:

386

answers:

3

I am investigating encoding of date information into a linear barcode that must be as short as possible. One idea we have had is encoding date information rather than using the ASCII characters for the date numerals.

  1. The earliest date to be encoded is 01-JAN-2009
  2. Date must be encoded using printable ASCII characters
+3  A: 

Use the date itself: 01/01/2009 is a perfectly acceptable barcode under the Code39 style barcode.

If you don't mind a bit of processing logic during read, then you can do things like remove the "/" or whatever separator character you use.

Basically you would encode something like, "01012009" into the barcode, and then have the decode process just read the first two numbers as the month, the next two as the day, and the last 4 as the year. Since they're straight ascii it will work without any really hard processing.

A second alternative is to have 01-Jan-2009 as your "0" date, and then just encode the number of days since then. At which the decoding process would be to read the number, and then add that many days to 1/1/09. This would work that, Jan/5/2009 would be encoded as a "4" then when you wanted to read the date back out, you'd add 4 to Jan/1/09 to get Jan/5/09.

Stephen Wrighton
if utilizing 8-digit date storage it makes optimum sense to store it as yyyymmdd soas to make it readable, sortable, and errorproof through the year 9999
Hardryv
+3  A: 

If only the date matters (not the time):

 Take the date to be encoded.
 Subtract 1-1-2009 from it
 Get the amount of elapsed days.

To encode this number as a printable sequence of ascii chars(ascii 48-127) do the following

pseudo code:

 const int ASCIILOWRANGE = 48
 const int ASCIIHIGHRANGE = 126
 const char ASCIIENDMARKER = 127;


 String convertToAscii(int numberOfDays)
 {
       String output = "";

       while(numberOfDays>0)
       {
           output += (char) ASCIILOWRANGE + numberOfDays % (ASCIIHIGHRANGE-ASCIILOWRANGE);
           numberOfDays /= (ASCIIHIGHRANGE-ASCIILOWRANGE);
       }
       output += ASCIIENDMARKER ;
       return output;
 }

 //decoder
 int convertToDays(String ascii)
 {
      char rightmost;
      int numberOfDays = 0;
      while(ascii.length>0)
      {
       rightmost = ascii[0];
           if(rightmost == ASCIIENDMARKER ) break; //ready

           numberOfDays *= (rightmost - ASCIILOWRANGE) * (ASCIIHIGHRANGE-ASCIILOWRANGE);
           ascii = ascii.substr(1); //remove rightmost char from string
      }
      return numberOfDays ;
 }

this way of encoding is the most dense. Since it encodes upto 96 days into the future in just 2 chars. 9216 days, in 3 chars, 884736 days in 4 chars.

Toad
This seems to be tighter than my idea above, but only seems to reach 24 years into the future with 3 characters. Am I figuring something wrong?
Aidan Ryan
yes... with every character the time goes up a factor 96. So for instance 8 characters would give us: 96^7 days = 205876021399 years. So it think it is future proof ;^)
Toad
to visualise it better... it is like decimal uses base 10. Hex uses base 16. This method uses base 96 (96 printable ascii chars). so counting goes like this a,b,c,..... aa,ab,ac,ad,ae........ba,bb,bc,bd,.... ...... aaa,aab,aac,aad etc
Toad
My point was that it seemed to fit a shorter range into the same number of characters. I see now that the terminator character is what makes the difference. Assuming the terminator is not required (date is always at the end of the barcode,) this algorithm does seem to be the tightest, reaching 884,767 (about 2,400 years) in three characters.
Aidan Ryan
Caveat for future visitors of this answer: "days since day X" encodings are susceptible to leap year issues!
Aidan Ryan
why a leap year issue? can you elaborate? If the base date (1-1-2009) doesn't change. Then X days after this date will always be the same date. Or am I missing something?
Toad
A: 

A very simple encoding would be using ASCII decimal 33 ("!") to represent zero through ASCII decimal 126 ("~") to represent 93. This could provide

1 character for day of month

1 character for month

1 or more characters representing the year

(for years 2009 to 2100, 1 character needed. One additional character needed for every 92 additional years)

So dates until 31-Dec-2100 could be represented with 3 characters.

Note that this answer is not as efficient as reinier's and Stephen's suggestion to use the number of days since the start date. It does, however, sidestep leap year issues.

Aidan Ryan