datetime.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 717 行 · 第 1/2 页

C
717
字号
	fmt_ystart = strstr(fmt, "yy");	fmt_mstart = strstr(fmt, "mm");	fmt_dstart = strstr(fmt, "dd");	if (!fmt_ystart || !fmt_mstart || !fmt_dstart)	{		errno = PGTYPES_DATE_ERR_EARGS;		return -1;	}	if (fmt_ystart < fmt_mstart)	{		/* y m */		if (fmt_dstart < fmt_ystart)		{			/* d y m */			fmt_token_order = "dym";		}		else if (fmt_dstart > fmt_mstart)		{			/* y m d */			fmt_token_order = "ymd";		}		else		{			/* y d m */			fmt_token_order = "ydm";		}	}	else	{		/* fmt_ystart > fmt_mstart */		/* m y */		if (fmt_dstart < fmt_mstart)		{			/* d m y */			fmt_token_order = "dmy";		}		else if (fmt_dstart > fmt_ystart)		{			/* m y d */			fmt_token_order = "myd";		}		else		{			/* m d y */			fmt_token_order = "mdy";		}	}	/*	 * handle the special cases where there is no delimiter between the	 * digits. If we see this:	 *	 * only digits, 6 or 8 bytes then it might be ddmmyy and ddmmyyyy (or	 * similar)	 *	 * we reduce it to a string with delimiters and continue processing	 */	/* check if we have only digits */	reading_digit = 1;	for (i = 0; str[i]; i++)	{		if (!isdigit((unsigned char) str[i]))		{			reading_digit = 0;			break;		}	}	if (reading_digit)	{		int			frag_length[3];		int			target_pos;		i = strlen(str);		if (i != 8 && i != 6)		{			errno = PGTYPES_DATE_ERR_ENOSHORTDATE;			return -1;		}		/* okay, this really is the special case */		/*		 * as long as the string, one additional byte for the terminator and 2		 * for the delimiters between the 3 fiedls		 */		str_copy = pgtypes_alloc(strlen(str) + 1 + 2);		if (!str_copy)			return -1;		/* determine length of the fragments */		if (i == 6)		{			frag_length[0] = 2;			frag_length[1] = 2;			frag_length[2] = 2;		}		else		{			if (fmt_token_order[0] == 'y')			{				frag_length[0] = 4;				frag_length[1] = 2;				frag_length[2] = 2;			}			else if (fmt_token_order[1] == 'y')			{				frag_length[0] = 2;				frag_length[1] = 4;				frag_length[2] = 2;			}			else			{				frag_length[0] = 2;				frag_length[1] = 2;				frag_length[2] = 4;			}		}		target_pos = 0;		/*		 * XXX: Here we could calculate the positions of the tokens and save		 * the for loop down there where we again check with isdigit() for		 * digits.		 */		for (i = 0; i < 3; i++)		{			int			start_pos = 0;			if (i >= 1)				start_pos += frag_length[0];			if (i == 2)				start_pos += frag_length[1];			strncpy(str_copy + target_pos, str + start_pos,					frag_length[i]);			target_pos += frag_length[i];			if (i != 2)			{				str_copy[target_pos] = ' ';				target_pos++;			}		}		str_copy[target_pos] = '\0';	}	else	{		str_copy = pgtypes_strdup(str);		if (!str_copy)			return -1;		/* convert the whole string to lower case */		for (i = 0; str_copy[i]; i++)			str_copy[i] = (char) pg_tolower((unsigned char) str_copy[i]);	}	/* look for numerical tokens */	reading_digit = 0;	token_count = 0;	for (i = 0; i < strlen(str_copy); i++)	{		if (!isdigit((unsigned char) str_copy[i]) && reading_digit)		{			/* the token is finished */			token[token_count][1] = i - 1;			reading_digit = 0;			token_count++;		}		else if (isdigit((unsigned char) str_copy[i]) && !reading_digit)		{			/* we have found a token */			token[token_count][0] = i;			reading_digit = 1;		}	}	/*	 * we're at the end of the input string, but maybe we are still reading a	 * number...	 */	if (reading_digit)	{		token[token_count][1] = i - 1;		token_count++;	}	if (token_count < 2)	{		/*		 * not all tokens found, no way to find 2 missing tokens with string		 * matches		 */		free(str_copy);		errno = PGTYPES_DATE_ERR_ENOSHORTDATE;		return -1;	}	if (token_count != 3)	{		/*		 * not all tokens found but we may find another one with string		 * matches by testing for the months names and months abbreviations		 */		char	   *month_lower_tmp = pgtypes_alloc(PGTYPES_DATE_MONTH_MAXLENGTH);		char	   *start_pos;		int			j;		int			offset;		int			found = 0;		char	  **list;		if (!month_lower_tmp)		{			/* free variables we alloc'ed before */			free(str_copy);			return -1;		}		list = pgtypes_date_months;		for (i = 0; list[i]; i++)		{			for (j = 0; j < PGTYPES_DATE_MONTH_MAXLENGTH; j++)			{				month_lower_tmp[j] = (char) pg_tolower((unsigned char) list[i][j]);				if (!month_lower_tmp[j])				{					/* properly terminated */					break;				}			}			if ((start_pos = strstr(str_copy, month_lower_tmp)))			{				offset = start_pos - str_copy;				/*				 * sort the new token into the numeric tokens, shift them if				 * necessary				 */				if (offset < token[0][0])				{					token[2][0] = token[1][0];					token[2][1] = token[1][1];					token[1][0] = token[0][0];					token[1][1] = token[0][1];					token_count = 0;				}				else if (offset < token[1][0])				{					token[2][0] = token[1][0];					token[2][1] = token[1][1];					token_count = 1;				}				else					token_count = 2;				token[token_count][0] = offset;				token[token_count][1] = offset + strlen(month_lower_tmp) - 1;				/*				 * the value is the index of the month in the array of months				 * + 1 (January is month 0)				 */				token_values[token_count] = i + 1;				found = 1;				break;			}			/*			 * evil[tm] hack: if we read the pgtypes_date_months and haven't			 * found a match, reset list to point to pgtypes_date_months_short			 * and reset the counter variable i			 */			if (list == pgtypes_date_months)			{				if (list[i + 1] == NULL)				{					list = months;					i = -1;				}			}		}		if (!found)		{			free(month_lower_tmp);			free(str_copy);			errno = PGTYPES_DATE_ERR_ENOTDMY;			return -1;		}		/*		 * here we found a month. token[token_count] and		 * token_values[token_count] reflect the month's details.		 *		 * only the month can be specified with a literal. Here we can do a		 * quick check if the month is at the right position according to the		 * format string because we can check if the token that we expect to		 * be the month is at the position of the only token that already has		 * a value. If we wouldn't check here we could say "December 4 1990"		 * with a fmt string of "dd mm yy" for 12 April 1990.		 */		if (fmt_token_order[token_count] != 'm')		{			/* deal with the error later on */			token_values[token_count] = -1;		}		free(month_lower_tmp);	}	/* terminate the tokens with ASCII-0 and get their values */	for (i = 0; i < 3; i++)	{		*(str_copy + token[i][1] + 1) = '\0';		/* A month already has a value set, check for token_value == -1 */		if (token_values[i] == -1)		{			errno = 0;			token_values[i] = strtol(str_copy + token[i][0], (char **) NULL, 10);			/* strtol sets errno in case of an error */			if (errno)				token_values[i] = -1;		}		if (fmt_token_order[i] == 'd')			tm.tm_mday = token_values[i];		else if (fmt_token_order[i] == 'm')			tm.tm_mon = token_values[i];		else if (fmt_token_order[i] == 'y')			tm.tm_year = token_values[i];	}	free(str_copy);	if (tm.tm_mday < 1 || tm.tm_mday > 31)	{		errno = PGTYPES_DATE_BAD_DAY;		return -1;	}	if (tm.tm_mon < 1 || tm.tm_mon > MONTHS_PER_YEAR)	{		errno = PGTYPES_DATE_BAD_MONTH;		return -1;	}	if (tm.tm_mday == 31 && (tm.tm_mon == 4 || tm.tm_mon == 6 || tm.tm_mon == 9 || tm.tm_mon == 11))	{		errno = PGTYPES_DATE_BAD_DAY;		return -1;	}	if (tm.tm_mon == 2 && tm.tm_mday > 29)	{		errno = PGTYPES_DATE_BAD_DAY;		return -1;	}	*d = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - date2j(2000, 1, 1);	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?