Skip to content

Commit d6928f2

Browse files
author
freddy77
committed
improve ms time/date conversions
1 parent 8a603f5 commit d6928f2

File tree

3 files changed

+132
-50
lines changed

3 files changed

+132
-50
lines changed

ChangeLog

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Mon Aug 8 14:33:22 CEST 2011 Frediano Ziglio <freddy77_A_gmail_D_com>
2+
* include/tdsconvert.h src/tds/convert.c:
3+
- improve ms time/date conversions
4+
15
Mon Aug 8 14:32:12 CEST 2011 Frediano Ziglio <freddy77_A_gmail_D_com>
26
* include/tdsconvert.h src/dblib/bcp.c src/dblib/dblib.c:
37
* src/odbc/convert_tds2sql.c src/tds/convert.c:
@@ -658,4 +662,4 @@ Sat Apr 9 16:15:00 EDT 2011 JK Lowden <[email protected]>
658662
* ChangeLog-0.91 added because of release
659663

660664
$FreeTDS$
661-
$Id: ChangeLog,v 1.3350 2011/08/08 12:32:07 freddy77 Exp $
665+
$Id: ChangeLog,v 1.3351 2011/08/08 12:33:18 freddy77 Exp $

include/tdsconvert.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extern "C"
3232
#endif
3333
#endif
3434

35-
/* $Id: tdsconvert.h,v 1.28 2011/08/08 12:32:07 freddy77 Exp $ */
35+
/* $Id: tdsconvert.h,v 1.29 2011/08/08 12:33:18 freddy77 Exp $ */
3636

3737
typedef union conv_result
3838
{
@@ -47,6 +47,7 @@ typedef union conv_result
4747
TDS_MONEY4 m4;
4848
TDS_DATETIME dt;
4949
TDS_DATETIME4 dt4;
50+
TDS_DATETIMEALL dta;
5051
TDS_NUMERIC n;
5152
TDS_CHAR *ib;
5253
TDS_UNIQUE u;

src/tds/convert.c

Lines changed: 125 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
#include <dmalloc.h>
6464
#endif
6565

66-
TDS_RCSID(var, "$Id: convert.c,v 1.212 2011/08/08 12:32:07 freddy77 Exp $");
66+
TDS_RCSID(var, "$Id: convert.c,v 1.213 2011/08/08 12:33:18 freddy77 Exp $");
6767

6868
typedef unsigned short utf16_t;
6969

@@ -486,6 +486,10 @@ tds_convert_char(int srctype, const TDS_CHAR * src, TDS_UINT srclen, int desttyp
486486
break;
487487
case SYBDATETIME:
488488
case SYBDATETIME4:
489+
case SYBMSTIME:
490+
case SYBMSDATE:
491+
case SYBMSDATETIME2:
492+
case SYBMSDATETIMEOFFSET:
489493
/* FIXME not null terminated */
490494
return string_to_datetime(src, desttype, cr);
491495
break;
@@ -1240,38 +1244,101 @@ tds_convert_money(int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT *
12401244
}
12411245

12421246
static TDS_INT
1243-
tds_convert_datetime(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr)
1247+
tds_convert_datetimeall(const TDSCONTEXT * tds_ctx, int srctype, const TDS_DATETIMEALL * dta, int desttype, CONV_RESULT * cr)
12441248
{
1249+
char whole_date_string[64];
1250+
TDSDATEREC when;
1251+
1252+
switch (desttype) {
1253+
case TDS_CONVERT_CHAR:
1254+
case CASE_ALL_CHAR:
1255+
memset(&when, 0, sizeof(when));
12451256

1246-
TDS_INT dt_days, dt_time;
1257+
tds_datecrack(srctype, dta, &when);
1258+
tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->date_fmt, &when,
1259+
dta->time_prec);
1260+
1261+
return string_to_result(whole_date_string, cr);
1262+
case CASE_ALL_BINARY:
1263+
/* TODO */
1264+
break;
1265+
case SYBDATETIME:
1266+
/* TODO check overflow */
1267+
cr->dt.dtdays = dta->date;
1268+
cr->dt.dttime = dta->time * 3u / 100000u;
1269+
return sizeof(TDS_DATETIME);
1270+
case SYBDATETIME4:
1271+
/* TODO check overflow */
1272+
cr->dt4.days = dta->date;
1273+
cr->dt4.minutes = dta->time / (60u * 10000000u);
1274+
return sizeof(TDS_DATETIME4);
1275+
case SYBMSDATETIMEOFFSET:
1276+
case SYBMSDATE:
1277+
case SYBMSTIME:
1278+
case SYBMSDATETIME2:
1279+
cr->dta = *dta;
1280+
return sizeof(TDS_DATETIMEALL);
1281+
/* conversions not allowed */
1282+
case SYBUNIQUE:
1283+
case SYBBIT:
1284+
case SYBBITN:
1285+
case SYBINT1:
1286+
case SYBINT2:
1287+
case SYBINT4:
1288+
case SYBINT8:
1289+
case SYBMONEY4:
1290+
case SYBMONEY:
1291+
case SYBNUMERIC:
1292+
case SYBDECIMAL:
1293+
default:
1294+
break;
1295+
}
1296+
return TDS_CONVERT_NOAVAIL;
1297+
}
12471298

1248-
char whole_date_string[30];
1299+
static TDS_INT
1300+
tds_convert_datetime(const TDSCONTEXT * tds_ctx, int srctype, const TDS_DATETIME * dt, int desttype, CONV_RESULT * cr)
1301+
{
1302+
char whole_date_string[64];
12491303
TDSDATEREC when;
12501304

12511305
switch (desttype) {
12521306
case TDS_CONVERT_CHAR:
12531307
case CASE_ALL_CHAR:
12541308
memset(&when, 0, sizeof(when));
12551309

1256-
tds_datecrack(SYBDATETIME, src, &when);
1310+
tds_datecrack(SYBDATETIME, dt, &when);
12571311
tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->date_fmt, &when, 3);
12581312

12591313
return string_to_result(whole_date_string, cr);
1260-
break;
12611314
case CASE_ALL_BINARY:
1262-
return binary_to_result(src, sizeof(TDS_DATETIME), cr);
1263-
break;
1315+
return binary_to_result(dt, sizeof(TDS_DATETIME), cr);
12641316
case SYBDATETIME:
1265-
memcpy(&cr->dt, src, sizeof(TDS_DATETIME));
1317+
cr->dt = *dt;
12661318
return sizeof(TDS_DATETIME);
1267-
break;
12681319
case SYBDATETIME4:
1269-
memcpy(&dt_days, src, 4);
1270-
memcpy(&dt_time, src + 4, 4);
1271-
cr->dt4.days = dt_days;
1272-
cr->dt4.minutes = (dt_time / 300) / 60;
1320+
cr->dt4.days = dt->dtdays;
1321+
cr->dt4.minutes = (dt->dttime / 300) / 60;
12731322
return sizeof(TDS_DATETIME4);
1274-
break;
1323+
case SYBMSDATETIMEOFFSET:
1324+
case SYBMSDATE:
1325+
case SYBMSTIME:
1326+
case SYBMSDATETIME2:
1327+
memset(&cr->dta, 0, sizeof(cr->dta));
1328+
/* FIXME must be 0 if came from DATETIME4 */
1329+
cr->dta.time_prec = 3;
1330+
if (desttype == SYBMSDATETIMEOFFSET)
1331+
cr->dta.has_offset = 1;
1332+
if (desttype != SYBMSDATE) {
1333+
cr->dta.has_time = 1;
1334+
cr->dta.time_prec = 3;
1335+
cr->dta.time = ((TDS_UINT8) dt->dttime) * 100000u / 3u;
1336+
}
1337+
if (desttype != SYBMSTIME) {
1338+
cr->dta.has_date = 1;
1339+
cr->dta.date = dt->dtdays;
1340+
}
1341+
return sizeof(TDS_DATETIMEALL);
12751342
/* conversions not allowed */
12761343
case SYBUNIQUE:
12771344
case SYBBIT:
@@ -1291,26 +1358,24 @@ tds_convert_datetime(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * s
12911358
}
12921359

12931360
static TDS_INT
1294-
tds_convert_datetime4(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, int desttype, CONV_RESULT * cr)
1361+
tds_convert_datetime4(const TDSCONTEXT * tds_ctx, int srctype, const TDS_DATETIME4 * dt4, int desttype, CONV_RESULT * cr)
12951362
{
12961363
TDS_DATETIME dt;
12971364

1298-
#define DT4 ((TDS_DATETIME4*) src)
12991365
switch (desttype) {
13001366
case CASE_ALL_BINARY:
1301-
return binary_to_result(src, sizeof(TDS_DATETIME4), cr);
1367+
return binary_to_result(dt4, sizeof(TDS_DATETIME4), cr);
13021368
case SYBDATETIME4:
1303-
cr->dt4 = *DT4;
1369+
cr->dt4 = *dt4;
13041370
return sizeof(TDS_DATETIME4);
13051371
default:
13061372
break;
13071373
}
13081374

13091375
/* convert to DATETIME and use tds_convert_datetime */
1310-
dt.dtdays = DT4->days;
1311-
dt.dttime = DT4->minutes * (60u * 300u);
1312-
#undef DT4
1313-
return tds_convert_datetime(tds_ctx, SYBDATETIME, (TDS_CHAR *) &dt, desttype, cr);
1376+
dt.dtdays = dt4->days;
1377+
dt.dttime = dt4->minutes * (60u * 300u);
1378+
return tds_convert_datetime(tds_ctx, SYBDATETIME, &dt, desttype, cr);
13141379
}
13151380

13161381
static TDS_INT
@@ -1567,7 +1632,6 @@ TDS_INT
15671632
tds_convert(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
15681633
{
15691634
TDS_INT length = 0;
1570-
TDS_DATETIME dt;
15711635

15721636
assert(srclen >= 0 && srclen <= 2147483647u);
15731637

@@ -1618,20 +1682,13 @@ tds_convert(const TDSCONTEXT * tds_ctx, int srctype, const TDS_CHAR * src, TDS_U
16181682
case SYBMSDATE:
16191683
case SYBMSDATETIME2:
16201684
case SYBMSDATETIMEOFFSET:
1621-
#define dta ((TDS_DATETIMEALL *) (src))
1622-
memset(&dt, 0, sizeof(dt));
1623-
if (dta->has_time)
1624-
dt.dttime = (dta->time * 300u + 150u) / 10000000lu;
1625-
if (dta->has_date)
1626-
dt.dtdays = dta->date;
1627-
length = tds_convert_datetime(tds_ctx, SYBDATETIME, (const TDS_CHAR *) &dt, desttype, cr);
1628-
break;
1629-
#undef dta
1685+
length = tds_convert_datetimeall(tds_ctx, srctype, (const TDS_DATETIMEALL *) src, desttype, cr);
1686+
break;
16301687
case SYBDATETIME:
1631-
length = tds_convert_datetime(tds_ctx, srctype, src, desttype, cr);
1688+
length = tds_convert_datetime(tds_ctx, srctype, (const TDS_DATETIME* ) src, desttype, cr);
16321689
break;
16331690
case SYBDATETIME4:
1634-
length = tds_convert_datetime4(tds_ctx, srctype, src, desttype, cr);
1691+
length = tds_convert_datetime4(tds_ctx, srctype, (const TDS_DATETIME4* ) src, desttype, cr);
16351692
break;
16361693
case SYBLONGBINARY:
16371694
case CASE_ALL_BINARY:
@@ -1895,13 +1952,22 @@ string_to_datetime(const char *instr, int desttype, CONV_RESULT * cr)
18951952
dt_time = (t.tm_hour * 60 + t.tm_min) * 60 + t.tm_sec;
18961953
cr->dt.dttime = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
18971954
return sizeof(TDS_DATETIME);
1898-
} else {
1899-
/* SYBDATETIME4 */
1955+
}
1956+
if (desttype == SYBDATETIME4) {
19001957
cr->dt4.days = dt_days;
19011958
cr->dt4.minutes = t.tm_hour * 60 + t.tm_min;
19021959
return sizeof(TDS_DATETIME4);
19031960
}
19041961

1962+
cr->dta.has_offset = 0;
1963+
cr->dta.offset = 0;
1964+
cr->dta.has_date = 1;
1965+
cr->dta.date = dt_days;
1966+
cr->dta.has_time = 1;
1967+
cr->dta.time_prec = 7; /* TODO correct value */
1968+
dt_time = (t.tm_hour * 60 + t.tm_min) * 60 + t.tm_sec;
1969+
cr->dta.time = dt_time * 10000000u + t.tm_ns / 100u;
1970+
return sizeof(TDS_DATETIMEALL);
19051971
}
19061972

19071973
static int
@@ -2896,28 +2962,39 @@ day weekday week date
28962962
TDSRET
28972963
tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr)
28982964
{
2899-
2900-
const TDS_DATETIME *dt;
2901-
const TDS_DATETIME4 *dt4;
2902-
29032965
int dt_days;
29042966
unsigned int dt_time;
29052967

2906-
int years, months, days, ydays, wday, hours, mins, secs, ms;
2968+
int years, months, days, ydays, wday, hours, mins, secs, dms;
29072969
int l, n, i, j;
29082970

2909-
if (datetype == SYBDATETIME) {
2910-
dt = (const TDS_DATETIME *) di;
2971+
if (datetype == SYBMSDATE || datetype == SYBMSTIME
2972+
|| datetype == SYBMSDATETIME2 || datetype == SYBMSDATETIMEOFFSET) {
2973+
const TDS_DATETIMEALL *dta = (const TDS_DATETIMEALL *) di;
2974+
dt_days = (datetype == SYBMSTIME) ? 0 : dta->date;
2975+
if (datetype == SYBMSTIME) {
2976+
dms = 0;
2977+
secs = 0;
2978+
dt_time = 0;
2979+
} else {
2980+
dms = dta->time % 10000000u;
2981+
dt_time = dta->time / 10000000u;
2982+
secs = dt_time % 60;
2983+
dt_time = dt_time / 60;
2984+
dt_days = dta->date;
2985+
}
2986+
} else if (datetype == SYBDATETIME) {
2987+
const TDS_DATETIME *dt = (const TDS_DATETIME *) di;
29112988
dt_time = dt->dttime;
2912-
ms = ((dt_time % 300) * 1000 + 150) / 300;
2989+
dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
29132990
dt_time = dt_time / 300;
29142991
secs = dt_time % 60;
29152992
dt_time = dt_time / 60;
29162993
dt_days = dt->dtdays;
29172994
} else if (datetype == SYBDATETIME4) {
2918-
dt4 = (const TDS_DATETIME4 *) di;
2995+
const TDS_DATETIME4 *dt4 = (const TDS_DATETIME4 *) di;
29192996
secs = 0;
2920-
ms = 0;
2997+
dms = 0;
29212998
dt_days = dt4->days;
29222999
dt_time = dt4->minutes;
29233000
} else
@@ -2956,7 +3033,7 @@ tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr)
29563033
dr->hour = hours;
29573034
dr->minute = mins;
29583035
dr->second = secs;
2959-
dr->decimicrosecond = ms * 10000u;
3036+
dr->decimicrosecond = dms;
29603037
return TDS_SUCCESS;
29613038
}
29623039

0 commit comments

Comments
 (0)