Borland Database Engine date decoding errors

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?
KlaxxonAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AVaulinCommented:
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.
0
KlaxxonAuthor Commented:
Thanks for your answer, but it does not work.

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

DBIDATE dte;
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.
0
AVaulinCommented:
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?
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

KlaxxonAuthor Commented:
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.
0
rlaytonCommented:
I believe DbiDateEncode requires 4 digits to calculate the correct date.  Try it, you'll like it!
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
KlaxxonAuthor Commented:
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:
DBIDATE dte;
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
0
rlaytonCommented:
Here is the exact code I use to encode/decode this stuff:

int Month, int Day, int Year;
DBIDATE Td;
 
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.


0
KlaxxonAuthor Commented:
aaaallllllrrrriiiiiigggggghhhhhhtttttttt!!!!!

(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.
0
KlaxxonAuthor Commented:
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.
0
rlaytonCommented:
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
      if(Blank)
      {
            switch(NumberType)
            {
                  case NINT:
                        memset(Src, 0, sizeof(int));
                        break;

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

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

                  default:
                        strcpy(Src, "");

            }
      }


      if(Status)
            ErrorHandler();

      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);

etc...


Good Luck!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.