We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now


Borland Database Engine date decoding errors

Klaxxon asked
Medium Priority
Last Modified: 2012-06-21
Hi, I'm learning-on-the-go as I develop a database application for a small business.  I'm running into a lot of trouble reading numerical and date data from a dBase III file using the Borland Database Engine and IDAPI.

The function was returning wierd values, so as an error-check I encoded then immediately decoded a date.  What I get back is not what I put in.

Help, please!

DbiDateEncode (2, 29, 80, &dte);
DbiDateDecode (dte, (pUINT16)&mm, (pUINT16)&dd, (pINT16)&yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);

Theoretically, the messagebox should display "2/29/80" but it actually displays something like "901286/13/3248237"

Any ideas?
Watch Question

You use DbiDateEncode and DbiDateDecode not correctly. 1st parameter in DbiDateEncode and 2nd, 3rd and 4th parameters in DbiDateDecode are references. You must write:
DbiDateEncode( 2, 29, 80, dte );
DbiDateDecode( dte, mm, dd, yy );
I hope this will help. Good luck.


Thanks for your answer, but it does not work.

My variables are declared as follows (as the online help file says they should be):

pUINT16 mm, dd;
pINT16 yy;

My code looks as you suggested:

DbiDateEncode (2, 29, 80, dte);
DbiDateDecode (dte, mm, dd, yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);            

But will not compile due to the following error:

Error:  superaje.c(583,34):Type mismatch in parameter 'pdateD' in call to 'DbiDateEncode'

I can get the code to compile as follows:

DbiDateEncode (2, 29, 80, &dte);
DbiDateDecode (dte, mm, dd, yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);            

(I added a '&' to dte in DbiDateEncode), but it crashes with a "Thread Stopped" message saying there was an "access violation".

Obviously, my understanding of pointers is rudimentary, so if you could help further, it would be appreciated.

Let's try this way:

long dte;
Word mm, dd;
short yy;

DbiDateEncode (2, 29, 80, dte);
sprintf (str, "%li", dte);
MessageBox (hDlg, str, "", MB_OK);
DbiDateDecode( dte, mm, dd, yy );
sprintf (str, "%hi/%hi/%hi", mm, dd, yy); // see h specifier
MessageBox (hDlg, str, "", MB_OK);

What both MessageBox says?


Nope ... doesn't work.
I get a bunch of "type mismatch" messages because the types need to be DBIDATE, pUINT16, and pINT16.

I'm working in Borland C++ 32-bit with Borland Database Engine 32-bit.
I believe DbiDateEncode requires 4 digits to calculate the correct date.  Try it, you'll like it!

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts


Thanks for the advise, unfortunately it didn't help.  For furthur clarification, here is the exact code I'm using, plus the exact results I get:

The variables are declared as follows:
pUINT16 mm, dd;
pINT16 yy;

This is the code:
/*  "Chk()" is simply an error-message printing function.  It's source can be found under "chk" in the bde32.hlp file  */

Chk (DbiDateEncode (4, 28, 96, &dte));
Chk (DbiDateDecode (dte, (pUINT16)&mm, (pUINT16)&dd, (pINT16)&yy));
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);

Here's the results with different dates:

when I encode:  5, 28, 1997
I get:  2064515077/28/133069
(at least the day works!)

encode:  5, 28, 97
get:  2064515077/28/131169

encode:  4, 28, 97
get:  2064515076/28/131169

encode:  4, 28, 96
get:  2064515076/28/131168

These results imply that I get simply subtract a particular value from each answer to get the right one.  This is the first time I actually did a trial-and-error check of the return values, and now it looks like they're always off by a consistant ammount.

I'd still like to have the function work properly, though.... I really bothers me to have to hack an answer out.

BTW, I ran the DbiGetDateFormat() function, and it returned the following:
DateFormat = 0
4 digit year = 0
Year biased = 1
date separator = '/'

The explanations of those are in the help file, but those values are as they should be.

As some additional background, I'm writing a program that reads in a dBase III .DBF file.  I was getting weird values when reading dates, so *that's* why I encoded then decoded a date... It's purpose is simply an error check.

Thanks for your help, I hope I've clarified a few things, and I hope you can assist me further...  My employer is getting anxious to see some results and this problem has been a major roadblock.
       - Klaxxon

Here is the exact code I use to encode/decode this stuff:

int Month, int Day, int Year;
DbiDateEncode(Month, Day, Year, &Td);
DbiDateDecode(Td, &Month, &Day, &Year);

This stuff is actually quite straight forward, and I haven't had any problems with it once I got it all setup and working correctly.  

The only other problem I can see is if the memory for the table buffer isn't allocated correctly.  Also, view the contents of the Td  ( the DBIDATE / double) variable after encoding each of the different trial dates, and see what relationship they have.  

I've never used the BDE with dBaseIII, but I've plenty of success using it with Paradox, MS SQL Server, and Sybase, which should basically be the same using it with any other DataBase

Anyway, Good luck!

PS. I have a DataBase/Table wrapper class I've written which encapsulates all this stuff, automating file opening, record access, etc...,  which really makes it much easier to manage (at least for me.)  If you're interested let me know,  I'd consider letting somebody else try it out!  However it may take you longer to get it set up than you have to waste.



(you'll have to excuse me, but this problem has been really bothering me... and now it's FIXED!!!)  :o)

For some unknown reason, if the month, day, and year variables have not been assigned a value (it appears any value will do) before DbiDateDecode (dte, &mm, &dd, &yy); is called, then I get screwy answers.  All I did was assign mm = dd = yy = 1; at the top of the function, and now DbiDateDecode returns everything correctly!!  Wahoo!

I figured that out because in your code you fed DbiDateEncode preassigned values while I was trying to pass numbers directly to the function.  This led me to do a little playing around, and I figured it out.

Thank you *VERY* much.

.....Now, on with my program!

PS:  You *may* see a question posted here soon about reading regular numerical data (as opposed to strings) from a database.  But I'll see what I can do first.  Thanks a bunch.


Yup.... I'm having problems with reading numerical data.  YaSee, this is the first time I've ever used BDE so I'm learning as I go.

Say a field contains an integer.  Do I just do the following?

int num;
DbiGetField (VarCur, FieldNum, RecBuff, (pBYTE)num, ...);

or do I use:
..., (pBYTE)&num, ...

or do I declare num as a string or perhaps a double?

If you could send me some sample source either as a comment to this question or to rogersa@superaje.com ,  I'd really appreciate it.

If you like, I can submit it as a 25 or 50 point question and then grade you.

Thanks in advance.

I'll give this one to you, just treat me well when the opportunity arises.

If the value you are retrieving is a double, then pass in a double, likewise with int, char*,etc...

Here is a snippet from my table class...

char * Table::GetField (UINT16 FieldNum, char *Src)
      BOOL Blank;

      strcpy(Action, "GetField");

      Status = DbiGetField (Cursor, FieldNum, DBRec, (pBYTE)Src, &Blank);

//Not always blank in SQL Server
                  case NINT:
                        memset(Src, 0, sizeof(int));

                  case NDOUBLE:
                        memset(Src, 0, sizeof(double));

                  case NLONG:
                        memset(Src, 0, sizeof(long));

                        strcpy(Src, "");



      return Src;


double Table::GetField(UINT16 FieldNum, double &Number)
      NumberType = NDOUBLE;

      GetField(FieldNum, (char *)&Number);

      return Number;

int Table::GetField(UINT16 FieldNum, int &Number)
      NumberType = NINT;

      GetField(FieldNum, (char *)&Number);

      return Number;

long Table::GetField(UINT16 FieldNum, long &Number)
      NumberType = NLONG;

      GetField(FieldNum, (char *)&Number);

      return Number;

As you can see, I simply pass in the variable of the type I want to retrieve, which forces the correct function to be called, and the variable is also returned for ease of use!  Each function calls the top (top as in top of this listing) function, so you could look at that one for reference.  The Cursor and Record are both part of the class, so you'll need to pass those in as well.

Quick examples for use:

double Double;
int Integer;
char Str[MAX_SIZE];

wsprintf(Temp, "%d \t %lf", GetField(FieldNum, Integer), GetField(FieldNum, Double));
MessageBox(0, GetField(FieldNum, Str), Title, MB_OK);


Good Luck!
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.