/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Authors: Jeffrey Stedfast * * Copyright 2000 Ximian, Inc. (www.ximian.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ #include #include #include #include "broken-date-parser.h" /* prototypes for functions dealing with broken date formats */ static GList *datetok (const gchar *date); static gint get_days_in_month (gint mon, gint year); static gint get_weekday (gchar *str); static gint get_month (gchar *str); static char *tz_months [] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /***************************************************************************** * The following functions are here in the case of badly broken date formats * * * * -- fejj@ximian.com * *****************************************************************************/ typedef struct { gchar dow[6]; /* day of week (should only need 4 chars) */ gint day; gint mon; /* 1->12 or 0 if invalid */ gint year; gint hour; gint min; gint sec; gchar zone[6]; /* time zone */ } date_t; static GList *datetok (const gchar *date) { GList *tokens = NULL; gchar *token, *start, *end; start = (gchar *) date; while (*start) { /* find the end of this token */ for (end = start; *end && *end != ' '; end++); token = g_strndup (start, (end - start)); if (token && *token) tokens = g_list_append (tokens, token); else g_free (token); if (*end) start = end + 1; else break; } return tokens; } static gint get_days_in_month (gint mon, gint year) { switch (mon) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31; case 4: case 6: case 9: case 11: return 30; case 2: if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) return 29; return 28; default: return 30; } } static gint get_weekday (gchar *str) { g_return_val_if_fail ((str != NULL), 0); if (strncmp (str, "Mon", 3) == 0) { return 1; } else if (strncmp (str, "Tue", 3) == 0) { return 2; } else if (strncmp (str, "Wed", 3) == 0) { return 3; } else if (strncmp (str, "Thu", 3) == 0) { return 4; } else if (strncmp (str, "Fri", 3) == 0) { return 5; } else if (strncmp (str, "Sat", 3) == 0) { return 6; } else if (strncmp (str, "Sun", 3) == 0) { return 7; } return 0; /* unknown week day */ } static gint get_month (gchar *str) { g_return_val_if_fail (str != NULL, 0); if (strncmp (str, "Jan", 3) == 0) { return 1; } else if (strncmp (str, "Feb", 3) == 0) { return 2; } else if (strncmp (str, "Mar", 3) == 0) { return 3; } else if (strncmp (str, "Apr", 3) == 0) { return 4; } else if (strncmp (str, "May", 3) == 0) { return 5; } else if (strncmp (str, "Jun", 3) == 0) { return 6; } else if (strncmp (str, "Jul", 3) == 0) { return 7; } else if (strncmp (str, "Aug", 3) == 0) { return 8; } else if (strncmp (str, "Sep", 3) == 0) { return 9; } else if (strncmp (str, "Oct", 3) == 0) { return 10; } else if (strncmp (str, "Nov", 3) == 0) { return 11; } else if (strncmp (str, "Dec", 3) == 0) { return 12; } return 0; /* unknown month */ } gchar * parse_broken_date (const gchar *datestr) { GList *tokens; date_t date; gchar *token, *ptr, *newdatestr; guint len, i, retval; gdouble tz = 0.0; memset ((void*)&date, 0, sizeof (date_t)); g_return_val_if_fail (datestr != NULL, NULL); tokens = datetok (datestr); len = g_list_length (tokens); for (i = 0; i < len; i++) { token = g_list_nth_data (tokens, i); if ((retval = get_weekday (token))) { strncpy (date.dow, datestr, 4); } else if ((retval = get_month (token))) { date.mon = retval; } else if (strlen (token) <= 2) { /* this could be a 1 or 2 digit day of the month */ for (retval = 1, ptr = token; *ptr; ptr++) if (*ptr < '0' || *ptr > '9') retval = 0; if (retval && atoi (token) <= 31 && !date.day) /* probably should find a better way */ date.day = atoi (token); else /* fubar'd client using a 2-digit year */ date.year = atoi (token) < 69 ? 2000 + atoi (token) : 1900 + atoi (token); } else if (strlen (token) == 4) { /* this could be the year... */ for (retval = 1, ptr = token; *ptr; ptr++) if (*ptr < '0' || *ptr > '9') retval = 0; if (retval) date.year = atoi (token); } else if (strchr (token, ':')) { /* this must be the time: hh:mm:ss */ sscanf (token, "%d:%d:%d", &date.hour, &date.min, &date.sec); } else if (*token == '-' || *token == '+') { tz = atoi (token) / 100.0; } } g_list_free (tokens); /* adjust times based on time zones */ if (tz != 0) { /* check for time-zone shift */ if (tz > 0) { /* correct for positive hours off of UCT */ date.hour -= (tz / 100); tz = (gint)tz % 100; if (tz > 0) /* correct for positive minutes off of UCT */ date.min -= (gint)(((gdouble) tz / 100.0) * 60.0); } else { if (tz < 0) { /* correct for negative hours off of UCT */ tz = -tz; date.hour += (tz / 100); tz = -((gint)tz % 100); if (tz < 0) date.min -= (gint)(((gdouble) tz / 100.0) * 60.0); } } /* adjust seconds to proper range */ if (date.sec > 59) { date.min += (date.sec / 60); date.sec = (date.sec % 60); } /* adjust minutes to proper range */ if (date.min > 59) { date.hour += (date.min / 60); date.min = (date.min % 60); } else { if (date.min < 0) { date.min = -date.min; date.hour -= (date.min / 60) - 1; date.min = 60 - (date.min % 60); } } /* adjust hours to the proper randge */ if (date.hour > 23) { date.day += (date.hour / 24); date.hour -= (date.hour % 24); } else { if (date.hour < 0) { date.hour = -date.hour; date.day -= (date.hour / 24) - 1; date.hour = 24 - (date.hour % 60); } } /* adjust days to the proper range */ while (date.day > get_days_in_month (date.mon, date.year)) { date.day -= get_days_in_month (date.mon, date.year); date.mon++; if (date.mon > 12) { date.year += (date.mon / 12); date.mon = (date.mon % 12); if (date.mon == 0) { /* month sanity check */ date.mon = 12; date.year -= 1; } } } while (date.day < 1) { date.day += get_days_in_month (date.mon, date.year); date.mon--; if (date.mon < 1) { date.mon = -date.mon; date.year -= (date.mon / 12) - 1; date.mon = 12 - (date.mon % 12); } } /* adjust months to the proper range */ if (date.mon > 12) { date.year += (date.mon / 12); date.mon = (date.mon % 12); if (date.mon == 0) { /* month sanity check */ date.mon = 12; date.year -= 1; } } else { if (date.mon < 1) { date.mon = -date.mon; date.year -= (date.mon / 12) - 1; date.mon = 12 - (date.mon % 12); } } } /* now lets print this date into a string with the correct format */ newdatestr = g_strdup_printf ("%s, %d %s %d %s%d:%s%d:%s%d -0000", date.dow, date.day, tz_months[date.mon-1], date.year, date.hour > 10 ? "" : "0", date.hour, date.min > 10 ? "" : "0", date.min, date.sec > 10 ? "" : "0", date.sec); return newdatestr; } /***************************************************************************** * This ends the code for the broken date parser... * * * * -- fejj@ximian.com * *****************************************************************************/ /td>-4/+3 * Set maintainership back to ports@cs2012-06-032-2/+2 * - update png to 1.5.10dinoex2012-06-0115-16/+19 * Remove non-serving mirrorcs2012-05-201-2/+1 * - Adjust BOINC_* variables to be consistent with new system in boinc-clientpav2012-05-162-9/+9 * - Update to 0.48sunpoet2012-05-032-5/+5 * - Update to 1.3culot2012-04-262-3/+3 * - Update to 2.28wen2012-04-173-3/+4 * - Update to 1.2culot2012-04-163-16/+18 * - Update to 0.47wen2012-04-112-3/+3 * - Update to 1.0wen2012-03-223-4/+7 * - Revert ports/165605 as requested by portmgr@pgollucci2012-03-141-1/+7 * - Remove ports that only work with < perl 5.12 (devel/p5-B-Size, devel/p5-Dev...pgollucci2012-03-091-7/+1 * - Update to 1.59wen2012-03-063-1070/+1129 * - Update to 0.46wen2012-03-053-3/+12 * - Update to 0.4.5wen2012-02-232-3/+3 * - Update MASTER_SITES and WWW: linemiwi2012-02-203-20/+28 * update to 1.5.0.1.maho2012-02-164-40/+76 * - Update to 0.78sunpoet2012-02-113-44/+58 * - Update to 2.26sunpoet2012-02-113-5/+7 * - Update to 1.22sunpoet2012-02-092-3/+3 * - Update to 0.77wen2012-02-093-5/+8 * - fix build with gcc46dinoex2012-02-071-7/+4 * - Mark BROKEN on FreeBSD 9.X and up: does not compilepav2012-02-061-1/+7 * - Respect CCmiwi2012-01-281-1/+2 * At the moment 1385 ports use BUILD_DEPENDS= ${RUN_DEPENDS} and 450eadler2012-01-225-5/+5 * - Update to 3.23sylvio2012-01-172-3/+3 * Chase pdflib.so version and bump PORTREVISION accordingly.ale2012-01-101-2/+2 * - The proper acronym for Apache Software License 2 is really AL2tabthorpe2012-01-091-1/+1 * - Update to 0.87wen2011-12-233-4/+6 * - Update to 1.21sunpoet2011-11-242-4/+5 * - unbreakgahr2011-11-172-2/+29 * Does not build on powerpc-9: error in pthreads.linimon2011-11-101-0/+4 * - Remove WITH_FBSD10_FIX, is no longer neededmiwi2011-11-091-1/+0 * - Mark BROKEN: does not compile with new fltkpav2011-11-051-0/+2 * - Fix fetch and update WWWpav2011-11-052-2/+2 * - Fix build on FreeBSD 10miwi2011-10-291-0/+1 * - Update to 0.45sunpoet2011-10-292-3/+3 * The vast majority of pkg-descr files had the following format when theydougb2011-10-243-10/+1 * - remove maintainer tags from pkg-descreadler2011-10-23