Mercurial > pidgin
comparison src/util.c @ 13119:fcde3faa1f57
[gaim-migrate @ 15481]
This adds support for displaying log timestamps in their original timezone. If your OS's definition of struct tm sucks, then the log timestamps will show up in your local timezone, but converted, so the time is accurate. Yay! Anyway, this all works, as I've renamed lots of my log files locally, but currently, there's no code to save new logs in this name format. That's held up on a portability issue and backwards compatibility issue.
committer: Tailor Script <tailor@pidgin.im>
| author | Richard Laager <rlaager@wiktel.com> |
|---|---|
| date | Sat, 04 Feb 2006 20:55:52 +0000 |
| parents | d9d15ec284ca |
| children | f62d14ba98f6 |
comparison
equal
deleted
inserted
replaced
| 13118:8855973b487b | 13119:fcde3faa1f57 |
|---|---|
| 488 gaim_utf8_strftime(const char *format, const struct tm *tm) | 488 gaim_utf8_strftime(const char *format, const struct tm *tm) |
| 489 { | 489 { |
| 490 static char buf[128]; | 490 static char buf[128]; |
| 491 char *utf8; | 491 char *utf8; |
| 492 | 492 |
| 493 g_return_val_if_fail(format != NULL, NULL); | |
| 494 | |
| 495 if (tm == NULL) | |
| 496 { | |
| 497 time_t now = time(NULL); | |
| 498 tm = localtime(&now); | |
| 499 } | |
| 500 | |
| 493 /* A return value of 0 is either an error (in | 501 /* A return value of 0 is either an error (in |
| 494 * which case, the contents of the buffer are | 502 * which case, the contents of the buffer are |
| 495 * undefined) or the empty string (in which | 503 * undefined) or the empty string (in which |
| 496 * case, no harm is done here). */ | 504 * case, no harm is done here). */ |
| 497 if (strftime(buf, sizeof(buf), format, tm) == 0) | 505 if (strftime(buf, sizeof(buf), format, tm) == 0) |
| 520 { | 528 { |
| 521 return gaim_utf8_strftime(_("%x %X"), tm); | 529 return gaim_utf8_strftime(_("%x %X"), tm); |
| 522 } | 530 } |
| 523 | 531 |
| 524 const char * | 532 const char * |
| 525 gaim_date_format_full(time_t time) | 533 gaim_date_format_full(const struct tm *tm) |
| 526 { | 534 { |
| 527 return gaim_utf8_strftime("%c", localtime(&time)); | 535 return gaim_utf8_strftime("%c", tm); |
| 528 } | 536 } |
| 529 | 537 |
| 530 const char * | 538 const char * |
| 531 gaim_time_format(const struct tm *tm) | 539 gaim_time_format(const struct tm *tm) |
| 532 { | 540 { |
| 547 | 555 |
| 548 return mktime(&tm); | 556 return mktime(&tm); |
| 549 } | 557 } |
| 550 | 558 |
| 551 time_t | 559 time_t |
| 552 gaim_str_to_time(const char *timestamp, gboolean utc) | 560 gaim_str_to_time(const char *timestamp, gboolean utc, |
| 561 struct tm *tm, long *tz_off, const char **rest) | |
| 553 { | 562 { |
| 554 time_t retval = 0; | 563 time_t retval = 0; |
| 555 struct tm *t; | 564 struct tm *t; |
| 556 char buf[32]; | 565 const char *c = timestamp; |
| 557 char *c; | |
| 558 int year = 0; | 566 int year = 0; |
| 559 int tzoff = 0; | 567 long tzoff = GAIM_NO_TZ_OFF; |
| 560 | 568 |
| 561 time(&retval); | 569 time(&retval); |
| 562 t = localtime(&retval); | 570 t = localtime(&retval); |
| 563 | |
| 564 snprintf(buf, sizeof(buf), "%s", timestamp); | |
| 565 c = buf; | |
| 566 | 571 |
| 567 /* 4 digit year */ | 572 /* 4 digit year */ |
| 568 if (sscanf(c, "%04d", &year) && year > 1900) | 573 if (sscanf(c, "%04d", &year) && year > 1900) |
| 569 { | 574 { |
| 570 c += 4; | 575 c += 4; |
| 573 t->tm_year = year - 1900; | 578 t->tm_year = year - 1900; |
| 574 } | 579 } |
| 575 | 580 |
| 576 /* 2 digit month */ | 581 /* 2 digit month */ |
| 577 if (!sscanf(c, "%02d", &t->tm_mon)) | 582 if (!sscanf(c, "%02d", &t->tm_mon)) |
| 583 { | |
| 584 if (rest != NULL && *c != '\0') | |
| 585 *rest = c; | |
| 578 return 0; | 586 return 0; |
| 587 } | |
| 579 c += 2; | 588 c += 2; |
| 580 if (*c == '-' || *c == '/') | 589 if (*c == '-' || *c == '/') |
| 581 c++; | 590 c++; |
| 582 t->tm_mon -= 1; | 591 t->tm_mon -= 1; |
| 583 | 592 |
| 584 /* 2 digit day */ | 593 /* 2 digit day */ |
| 585 if (!sscanf(c, "%02d", &t->tm_mday)) | 594 if (!sscanf(c, "%02d", &t->tm_mday)) |
| 595 { | |
| 596 if (rest != NULL && *c != '\0') | |
| 597 *rest = c; | |
| 586 return 0; | 598 return 0; |
| 599 } | |
| 587 c += 2; | 600 c += 2; |
| 588 if (*c == '/') | 601 if (*c == '/') |
| 589 { | 602 { |
| 590 c++; | 603 c++; |
| 591 | 604 |
| 592 if (!sscanf(c, "%04d", &t->tm_year)) | 605 if (!sscanf(c, "%04d", &t->tm_year)) |
| 593 return 0; | 606 { |
| 607 if (rest != NULL && *c != '\0') | |
| 608 *rest = c; | |
| 609 return 0; | |
| 610 } | |
| 594 t->tm_year -= 1900; | 611 t->tm_year -= 1900; |
| 595 } | 612 } |
| 596 else if (*c == 'T' || *c == '.') { /* we have more than a date, keep going */ | 613 else if (*c == 'T' || *c == '.') |
| 597 c++; /* skip the "T" */ | 614 { |
| 615 c++; | |
| 616 /* we have more than a date, keep going */ | |
| 598 | 617 |
| 599 /* 2 digit hour */ | 618 /* 2 digit hour */ |
| 600 if (sscanf(c, "%02d:%02d:%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 || | 619 if ((sscanf(c, "%02d:%02d:%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 && (c = c + 8)) || |
| 601 sscanf(c, "%02d%02d%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3) { | 620 (sscanf(c, "%02d%02d%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 && (c = c + 6))) |
| 602 int tzhrs, tzmins; | 621 { |
| 603 c += 8; | 622 gboolean offset_positive = FALSE; |
| 604 if (*c == '.') /* dealing with precision we don't care about */ | 623 int tzhrs; |
| 624 int tzmins; | |
| 625 | |
| 626 t->tm_isdst = -1; | |
| 627 | |
| 628 if (*c == '.' && *(c+1) >= '0' && *(c+1) <= '9') /* dealing with precision we don't care about */ | |
| 605 c += 4; | 629 c += 4; |
| 606 if ((*c == '+' || *c == '-') && | 630 if (*c == '+') |
| 607 sscanf(c+1, "%02d:%02d", &tzhrs, &tzmins)) { | 631 offset_positive = TRUE; |
| 632 if (((*c == '+' || *c == '-') && (c = c + 1)) && | |
| 633 ((sscanf(c, "%02d:%02d", &tzhrs, &tzmins) == 2 && (c = c + 5)) || | |
| 634 (sscanf(c, "%02d%02d", &tzhrs, &tzmins) == 2 && (c = c + 4)))) | |
| 635 { | |
| 608 tzoff = tzhrs*60*60 + tzmins*60; | 636 tzoff = tzhrs*60*60 + tzmins*60; |
| 609 if (*c == '+') | 637 if (offset_positive) |
| 610 tzoff *= -1; | 638 tzoff *= -1; |
| 611 } | 639 /* We don't want the C library doing DST calculations |
| 612 | 640 * if we know the UTC offset already. */ |
| 613 t->tm_isdst = -1; | 641 t->tm_isdst = 0; |
| 614 | 642 } |
| 615 if (tzoff || utc) { | 643 |
| 644 if (rest != NULL && *c != '\0') | |
| 645 { | |
| 646 if (*c == ' ') | |
| 647 c++; | |
| 648 if (*c != '\0') | |
| 649 *rest = c; | |
| 650 } | |
| 651 | |
| 652 if (tzoff != GAIM_NO_TZ_OFF || utc) | |
| 653 { | |
| 654 #if defined(_WIN32) || defined(HAVE_TM_GMTOFF) || defined (HAVE_TIMEZONE) | |
| 655 if (tzoff == GAIM_NO_TZ_OFF) | |
| 656 tzoff = 0; | |
| 657 #endif | |
| 658 | |
| 616 #ifdef _WIN32 | 659 #ifdef _WIN32 |
| 617 TIME_ZONE_INFORMATION tzi; | 660 TIME_ZONE_INFORMATION tzi; |
| 618 DWORD ret; | 661 DWORD ret; |
| 619 if ((ret = GetTimeZoneInformation(&tzi)) | 662 if ((ret = GetTimeZoneInformation(&tzi)) != TIME_ZONE_ID_INVALID) |
| 620 != TIME_ZONE_ID_INVALID) { | 663 { |
| 621 tzoff -= tzi.Bias * 60; | 664 tzoff -= tzi.Bias * 60; |
| 622 if (ret == TIME_ZONE_ID_DAYLIGHT) { | 665 if (ret == TIME_ZONE_ID_DAYLIGHT) |
| 666 { | |
| 623 tzoff -= tzi.DaylightBias * 60; | 667 tzoff -= tzi.DaylightBias * 60; |
| 624 } | 668 } |
| 625 } | 669 } |
| 670 else | |
| 671 tzoff = GAIM_NO_TZ_OFF; | |
| 626 #else | 672 #else |
| 627 #ifdef HAVE_TM_GMTOFF | 673 #ifdef HAVE_TM_GMTOFF |
| 628 tzoff += t->tm_gmtoff; | 674 tzoff += t->tm_gmtoff; |
| 629 #else | 675 #else |
| 630 # ifdef HAVE_TIMEZONE | 676 # ifdef HAVE_TIMEZONE |
| 631 tzset(); /* making sure */ | 677 tzset(); /* making sure */ |
| 632 tzoff -= timezone; | 678 tzoff -= timezone; |
| 633 t->tm_isdst = 0; /* I think this might fix it */ | |
| 634 # endif | 679 # endif |
| 635 #endif | 680 #endif |
| 636 #endif /* _WIN32 */ | 681 #endif /* _WIN32 */ |
| 637 } | 682 } |
| 638 } | 683 } |
| 684 else | |
| 685 { | |
| 686 if (*rest != NULL && *c != '\0') | |
| 687 *rest = c; | |
| 688 } | |
| 689 } | |
| 690 | |
| 691 if (tm != NULL) | |
| 692 { | |
| 693 *tm = *t; | |
| 694 tm->tm_isdst = -1; | |
| 695 mktime(tm); | |
| 639 } | 696 } |
| 640 | 697 |
| 641 retval = mktime(t); | 698 retval = mktime(t); |
| 642 retval += tzoff; | 699 if (tzoff != GAIM_NO_TZ_OFF) |
| 700 retval += tzoff; | |
| 701 | |
| 702 if (tz_off != NULL) | |
| 703 *tz_off = tzoff; | |
| 643 | 704 |
| 644 return retval; | 705 return retval; |
| 645 } | 706 } |
| 646 | |
| 647 | 707 |
| 648 /************************************************************************** | 708 /************************************************************************** |
| 649 * Markup Functions | 709 * Markup Functions |
| 650 **************************************************************************/ | 710 **************************************************************************/ |
| 651 gboolean | 711 gboolean |
