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