|
28 | 28 | #endif |
29 | 29 | #endif |
30 | 30 |
|
| 31 | +#defineMAX_TZDISP_HOUR15/* maximum allowed hour part */ |
| 32 | +#defineSECS_PER_MINUTE60 |
| 33 | +#defineMINS_PER_HOUR60 |
| 34 | + |
31 | 35 | constchar*PROGRAM_NAME=NULL; |
32 | 36 |
|
33 | 37 | constchar*pgut_dbname=NULL; |
@@ -496,19 +500,91 @@ parse_uint64(const char *value, uint64 *result) |
496 | 500 | * Convert ISO-8601 format string to time_t value. |
497 | 501 | */ |
498 | 502 | bool |
499 | | -parse_time(constchar*value,time_t*time) |
| 503 | +parse_time(constchar*value,time_t*result) |
500 | 504 | { |
501 | 505 | size_tlen; |
| 506 | +intfields_num, |
| 507 | +tz=0, |
| 508 | +i; |
502 | 509 | char*tmp; |
503 | | -inti; |
504 | 510 | structtmtm; |
505 | 511 | charjunk[2]; |
506 | 512 |
|
507 | 513 | /* tmp = replace( value, !isalnum, ' ' ) */ |
508 | 514 | tmp=pgut_malloc(strlen(value)++1); |
509 | 515 | len=0; |
510 | | -for (i=0;value[i];i++) |
511 | | -tmp[len++]= (IsAlnum(value[i]) ?value[i] :' '); |
| 516 | +fields_num=1; |
| 517 | + |
| 518 | +while (*value) |
| 519 | +{ |
| 520 | +if (IsAlnum(*value)) |
| 521 | +{ |
| 522 | +tmp[len++]=*value; |
| 523 | +value++; |
| 524 | +} |
| 525 | +elseif (fields_num<6) |
| 526 | +{ |
| 527 | +fields_num++; |
| 528 | +tmp[len++]=' '; |
| 529 | +value++; |
| 530 | +} |
| 531 | +/* timezone field is 7th */ |
| 532 | +elseif ((*value=='-'||*value=='+')&&fields_num==6) |
| 533 | +{ |
| 534 | +inthr, |
| 535 | +min, |
| 536 | +sec=0; |
| 537 | +char*cp; |
| 538 | + |
| 539 | +errno=0; |
| 540 | +hr=strtol(value+1,&cp,10); |
| 541 | +if ((value+1)==cp||errno==ERANGE) |
| 542 | +return false; |
| 543 | + |
| 544 | +/* explicit delimiter? */ |
| 545 | +if (*cp==':') |
| 546 | +{ |
| 547 | +errno=0; |
| 548 | +min=strtol(cp+1,&cp,10); |
| 549 | +if (errno==ERANGE) |
| 550 | +return false; |
| 551 | +if (*cp==':') |
| 552 | +{ |
| 553 | +errno=0; |
| 554 | +sec=strtol(cp+1,&cp,10); |
| 555 | +if (errno==ERANGE) |
| 556 | +return false; |
| 557 | +} |
| 558 | +} |
| 559 | +/* otherwise, might have run things together... */ |
| 560 | +elseif (*cp=='\0'&&strlen(value)>3) |
| 561 | +{ |
| 562 | +min=hr %100; |
| 563 | +hr=hr /100; |
| 564 | +/* we could, but don't, support a run-together hhmmss format */ |
| 565 | +} |
| 566 | +else |
| 567 | +min=0; |
| 568 | + |
| 569 | +/* Range-check the values; see notes in datatype/timestamp.h */ |
| 570 | +if (hr<0||hr>MAX_TZDISP_HOUR) |
| 571 | +return false; |
| 572 | +if (min<0||min >=MINS_PER_HOUR) |
| 573 | +return false; |
| 574 | +if (sec<0||sec >=SECS_PER_MINUTE) |
| 575 | +return false; |
| 576 | + |
| 577 | +tz= (hr*MINS_PER_HOUR+min)*SECS_PER_MINUTE+sec; |
| 578 | +if (*value=='-') |
| 579 | +tz=-tz; |
| 580 | + |
| 581 | +fields_num++; |
| 582 | +value=cp; |
| 583 | +} |
| 584 | +/* wrong format */ |
| 585 | +elseif (!IsSpace(*value)) |
| 586 | +return false; |
| 587 | +} |
512 | 588 | tmp[len]='\0'; |
513 | 589 |
|
514 | 590 | /* parse for "YYYY-MM-DD HH:MI:SS" */ |
@@ -540,7 +616,25 @@ parse_time(const char *value, time_t *time) |
540 | 616 | /* determine whether Daylight Saving Time is in effect */ |
541 | 617 | tm.tm_isdst=-1; |
542 | 618 |
|
543 | | -*time=mktime(&tm); |
| 619 | +*result=mktime(&tm); |
| 620 | + |
| 621 | +/* adjust time zone */ |
| 622 | +if (tz!=0) |
| 623 | +{ |
| 624 | +time_tltime=time(NULL); |
| 625 | +structtm*ptm=gmtime(<ime); |
| 626 | +time_tgmt=mktime(ptm); |
| 627 | +time_toffset; |
| 628 | + |
| 629 | +/* UTC time */ |
| 630 | +*result-=tz; |
| 631 | + |
| 632 | +/* Get local time */ |
| 633 | +ptm=localtime(<ime); |
| 634 | +offset=ltime-gmt+ (ptm->tm_isdst ?3600 :0); |
| 635 | + |
| 636 | +*result+=offset; |
| 637 | +} |
544 | 638 |
|
545 | 639 | return true; |
546 | 640 | } |
|