package com.taobao.tddl.common.utils;
import java.util.Date;
/**
* mysql中将string转化为date的代码
*
* @since 5.0.0
*/
public class DateUtils {
public static final int TIME_DATETIME_ONLY = 0;
public static int internal_format_positions[] = { 0, 1, 2, 3, 4, 5, 6, 255 };
public static final int MAX_DATE_PARTS = 8;
// long log_10_int[] = new long[] { 1, 10, 100, 1000, 10000L, 100000L,
// 1000000L, 10000000L, 100000000L };
public static final int YY_PART_YEAR = 70;
@SuppressWarnings({ "deprecation", "unused" })
public static Date str_to_time(String str) {
int length = str.length();
int was_cut;
Date time = new Date(0);
int field_length;
int digits;
int year_length = 0;
int add_hours = 0, start_loop;
long not_zero_date, allow_space;
boolean is_internal_format;
int pos;
int last_field_pos = 0;
int cur_pos = 0;
int i;
int date[] = new int[MAX_DATE_PARTS];
int date_len[] = new int[MAX_DATE_PARTS];
int number_of_fields;
boolean found_delimitier = false, found_space = false;
int frac_pos;
int frac_len;
// DBUG_ENTER("str_to_datetime");
// DBUG_PRINT("ENTER",("str: %.*s",length,str));
//
// LINT_INIT(field_length);
was_cut = 0;
/* Skip space at start */
str = str.trim();
// for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
// ;
int end = str.length();
if (str.isEmpty() || !isdigit(str.charAt(0))) {
was_cut = 1;
return null;
}
// if (str == end || ! my_isdigit(&my_charset_latin1, *str))
// {
// *was_cut= 1;
// DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
// }
is_internal_format = false;
/*
* This has to be changed if want to activate different timestamp
* formats
*/
int format_position[] = internal_format_positions;
/*
* Calculate number of digits in first part. If length= 8 or >= 14 then
* year is of format YYYY. (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
*/
for (pos = 0; pos < str.length() && (isdigit(str.charAt(pos)) || str.charAt(pos) == 'T'); pos++)
;
// for (pos=str;
// pos != end && (my_isdigit(&my_charset_latin1,*pos) || *pos == 'T');
// pos++)
// ;
digits = pos;
// digits= (uint) (pos-str);
start_loop = 0; /* Start of scan loop */
date_len[format_position[0]] = 0; /* Length of year field */
if (pos == str.length() || str.charAt(pos) == '.') {
/* Found date in internal format (only numbers like YYYYMMDD) */
year_length = (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
field_length = year_length;
is_internal_format = true;
format_position = internal_format_positions;
} else {
if (format_position[0] >= 3) /* If year is after HHMMDD */
{
/*
* If year is not in first part then we have to determinate if
* we got a date field or a datetime field. We do this by
* checking if there is two numbers separated by space in the
* input.
*/
while (pos < end && !my_isspace(str.charAt(pos)))
pos++;
while (pos < end && !isdigit(str.charAt(pos)))
pos++;
if (pos == end) {
/* Date field. Set hour, minutes and seconds to 0 */
date[0] = date[1] = date[2] = date[3] = date[4] = 0;
start_loop = 5; /* Start with first date part */
}
}
field_length = format_position[0] == 0 ? 4 : 2;
}
// if (pos == end || *pos == '.')
// {
// /* Found date in internal format (only numbers like YYYYMMDD) */
// year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
// field_length= year_length;
// is_internal_format=true;
// format_position= internal_format_positions;
// }
// else
// {
// if (format_position[0] >= 3) /* If year is after HHMMDD */
// {
// /*
// If year is not in first part then we have to determinate if we got
// a date field or a datetime field.
// We do this by checking if there is two numbers separated by
// space in the input.
// */
// while (pos < end && !my_isspace(&my_charset_latin1, *pos))
// pos++;
// while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
// pos++;
// if (pos == end)
// {
// if (flags & TIME_DATETIME_ONLY)
// {
// *was_cut= 1;
// DBUG_RETURN(MYSQL_TIMESTAMP_NONE); /* Can't be a full datetime */
// }
// /* Date field. Set hour, minutes and seconds to 0 */
// date[0]= date[1]= date[2]= date[3]= date[4]= 0;
// start_loop= 5; /* Start with first date part */
// }
// }
//
// field_length= format_position[0] == 0 ? 4 : 2;
// }
/*
* Only allow space in the first "part" of the datetime field and: -
* after days, part seconds - before and after AM/PM (handled by code
* later) 2003-03-03 20:00:20 AM 20:00:20.000000 AM 03-03-2000
*/
i = max(format_position[0], format_position[1]);
if (i < format_position[2]) i = format_position[2];
// set_if_bigger(i,format_position[2]);
allow_space = ((1 << i) | (1 << format_position[6]));
allow_space &= (1 | 2 | 4 | 8);
not_zero_date = 0;
for (i = start_loop; i < MAX_DATE_PARTS - 1 && cur_pos != end && isdigit(str.charAt(cur_pos)); i++) {
int start = cur_pos;
int tmp_value = (str.charAt(cur_pos++) - '0');
/*
* Internal format means no delimiters; every field has a fixed
* width. Otherwise, we scan until we find a delimiter and discard
* leading zeroes -- except for the microsecond part, where leading
* zeroes are significant, and where we never process more than six
* digits.
*/
boolean scan_until_delim = !is_internal_format && ((i != format_position[6]));
while (cur_pos != end && isdigit(str.charAt(cur_pos)) && (scan_until_delim || (--field_length != 0))) {
tmp_value = tmp_value * 10 + (str.charAt(cur_pos) - '0');
cur_pos++;
}
date_len[i] = (cur_pos - start);
if (tmp_value > 999999) /* Impossible date part */
{
was_cut = 1;
return null;
}
date[i] = tmp_value;
not_zero_date |= tmp_value;
/* Length of next field */
field_length = format_position[i + 1] == 0 ? 4 : 2;
if ((last_field_pos = cur_pos) == end) {
i++; /* Register last found part */
break;
}
/* Allow a 'T' after day to allow CCYYMMDDT type of fields */
if (i == format_position[2] && str.charAt(cur_pos) == 'T') {
cur_pos++; /* ISO8601: CCYYMMDDThhmmss */
continue;
}
if (i == format_position[5]) /* Seconds */
{
if (str.charAt(cur_pos) == '.') /* Followed by part seconds */
{
cur_pos++;
field_length = 6; /* 6 digits */
}
continue;
}
while (cur_pos != end && (my_ispunct(str.charAt(cur_pos)) || my_isspace(str.charAt(cur_pos)))) {
if (my_isspace(str.charAt(cur_pos))) {
if (!((allow_space & (1 << i)) != 0)) {
was_cut = 1;
return null;
}
found_space = true;
}
cur_pos++;
found_delimitier = true; /* Should be a 'normal' date */
}
/* Check if next position is AM/PM */
if (i == format_position[6]) /* Seconds, time for AM/PM */
{
i++; /* Skip AM/PM part */
if (format_position[7] != 255) /* If using AM/PM */
{
if (cur_pos + 2 <= end && (str.charAt(cur_pos + 1) == 'M' || str.charAt(cur_pos) + 1 == 'm')) {
if (str.charAt(cur_pos) == 'p' || str.charAt(cur_pos) == 'P') add_hours = 12;
else if (str.charAt(cur_pos) != 'a' || str.charAt(cur_pos) != 'A') continue; /*
* Not
* AM
* /
* PM
*/
str += 2; /* Skip AM/PM */
/* Skip space after AM/PM */
while (cur_pos != end && my_isspace(str.charAt(cur_pos)))
cur_pos++;
}
}
}
last_field_pos = cur_pos;
}
// if (found_delimitier && !found_space
// && ((flags & TIME_DATETIME_ONLY) != 0)) {
// was_cut = 1;
// return null; /* Can't be a datetime */
// }
cur_pos = last_field_pos;
number_of_fields = i - start_loop;
while (i < MAX_DATE_PARTS) {
date_len[i] = 0;
date[i++] = 0;
}
if (!is_internal_format) {
year_length = date_len[format_position[0]];
if (!(year_length != 0)) /* Year must be specified */
{
was_cut = 1;
return null;
}
time.setYear(date[format_position[0]] - 1900);
// l_time->year= date[(uint) format_position[0]];
time.setMonth(date[format_position[1]] - 1);
// l_time->month= date[(uint) format_position[1]];
time.setDate(date[format_position[2]]);
// l_time->day= date[(uint) format_position[2]];
time.setHours(date[format_position[3]]);
time.setMinutes(date[format_position[4]]);
time.setSeconds(date[format_position[5]]);
// l_time->hour= date[(uint) format_position[3]];
// l_time->minute= date[(uint) format_position[4]];
// l_time->second= date[(uint) format_position[5]];
frac_pos = format_position[6];
frac_len = date_len[frac_pos];
// if (frac_len < 6)
// date[frac_pos]*= log_10_int[6 - frac_len];
// l_time->second_part= date[frac_pos];
if (format_position[7] != 255) {
if (time.getHours() > 12) {
was_cut = 1;
return null;
}
time.setHours(time.getHours() % 12 + add_hours);
}
} else {
time.setYear(date[0] - 1900);
time.setMonth(date[1] - 1);
time.setDate(date[2]);
time.setHours(date[3]);
time.setMinutes(date[4]);
time.setSeconds(date[5]);
// if (date_len[6] < 6)
// date[6]*= log_10_int[6 - date_len[6]];
// l_time->second_part=date[6];
}
// l_time->neg= 0;
if (year_length == 2 && (not_zero_date != 0)) time.setYear(time.getYear()
+ (time.getYear() < YY_PART_YEAR ? 2000 : 1900));
// l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
if (number_of_fields < 3 || time.getYear() > 9999 || time.getMonth() > 12 || time.getDate() > 31
|| time.getHours() > 23 || time.getMinutes() > 59 || time.getMinutes() > 59) {
/* Only give warning for a zero date if there is some garbage after */
if (!(not_zero_date != 0)) /* If zero date */
{
for (; cur_pos != end; cur_pos++) {
if (!my_isspace(str.charAt(cur_pos))) {
not_zero_date = 1; /* Give warning */
break;
}
}
}
// was_cut= test(not_zero_date);
return null;
}
if (check_date(time, not_zero_date != 0, was_cut)) return null;
// l_time->time_type= (number_of_fields <= 3 ?
// MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
for (; cur_pos != end; cur_pos++) {
if (!my_isspace(str.charAt(cur_pos))) {
was_cut = 1;
break;
}
}
return time;
}
public static boolean check_date(Date time, boolean not_zero_date, int was_cut) {
return false;
}
public static boolean my_ispunct(char v) {
switch (Character.getType(v)) {
case Character.CONNECTOR_PUNCTUATION:
case Character.DASH_PUNCTUATION:
case Character.END_PUNCTUATION:
case Character.FINAL_QUOTE_PUNCTUATION:
case Character.INITIAL_QUOTE_PUNCTUATION:
case Character.START_PUNCTUATION:
case Character.OTHER_PUNCTUATION:
return true;
}
return false;
}
public static int max(int i, int j) {
return i > j ? i : j;
}
public static boolean my_isspace(char v) {
return Character.isWhitespace(v);
}
public static boolean isdigit(char v) {
return Character.isDigit(v);
}
}