Преобразовать `Java.lang.String` TO` oracle.sql.TIMESTAMPTZ`

У меня есть следующие значения Java.lang.String, которые представляют String значение TIMESTAMPTZ. Мне нужно преобразовать эти Java.lang.String TO oracle.sql.TIMESTAMPTZ.

"2016-04-19 17:34:43.781 Asia/Calcutta",
"2016-04-30 20:05:02.002 8:00",
"2003-11-11 00:22:15.0 -7:00",
"2003-01-01 02:00:00.0 -7:00",
"2007-06-08 15:01:12.288 Asia/Bahrain",
"2016-03-08 17:17:35.301 Asia/Calcutta",
"1994-11-24 11:57:17.303"

Я попробовал это разными способами.

Пример 1:

Пробовал это, используя SimpleDateFormat

String[] timeZoneValues = new String[]{"2016-04-19 17:34:43.781 Asia/Calcutta", "2016-04-30 20:05:02.002 8:00", "2003-11-11 00:22:15.0 -7:00", "2003-01-01 02:00:00.0 -7:00", "2007-06-08 15:01:12.288 Asia/Bahrain", "2016-03-08 17:17:35.301 Asia/Calcutta", "1994-11-24 11:57:17.303"};
        for(String timeZoneValue: timeZoneValues){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX");
            try {
                simpleDateFormat.parse(timeZoneValue);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

Что выбрал Exception:

java.text.ParseException: Unparseable date: "2016-04-19 17:34:43.781 Asia/Calcutta"
    at java.text.DateFormat.parse(DateFormat.java:357)

Пример 2:

Пробовал его, преобразовывая эти значения String непосредственно в Timestamp или oracle.sql.TIMESTAMPTZ

String parse = "2016-04-19 17:34:43.781 8:00";
        try {
            Timestamp timestamp = Timestamp.valueOf("2016-04-19 17:34:43.781 8:00");
        }catch (Exception ex){
            ex.printStackTrace();
        }

Исключение:

java.lang.NumberFormatException: For input string: "781 8:000"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:492)
    at java.lang.Integer.parseInt(Integer.java:527)
    at java.sql.Timestamp.valueOf(Timestamp.java:253)

Пример 3:

String parse = "2016-04-19 17:34:43.781 Asia/Calcutta";
DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTimeNoMillis();
DateTime dateTime = dateTimeFormatter.parseDateTime(parse);
Timestamp timeStamp = new Timestamp(dateTime.getMillis());

Исключение:

Invalid format: "2016-04-19 17:34:43.781 Asia/Calcutta" is malformed at " 17:34:43.781 Asia/Calcutta"

Образец 4:

try {
TIMESTAMPTZ timestamptz = new TIMESTAMPTZ(connection, (String) colValue);
}catch (Exception ex){
ex.printStackTrace();
}

Исключение:

java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
    at java.sql.Timestamp.valueOf(Timestamp.java:249)
    at oracle.sql.TIMESTAMPTZ.toBytes(TIMESTAMPTZ.java:1919)
    at oracle.sql.TIMESTAMPTZ.<init>(TIMESTAMPTZ.java:253)

Я пытаюсь вставить значение TIMESTAMPTZ в базу Oracle, используя Apache Metamodel, и у меня есть Java 1.7, установленный в моей системе.

Ответ 1

Ваши временные метки не находятся в стандартных форматах синтаксиса java. Поэтому для их анализа вам нужно написать собственный код для обработки таких форматов.

Пара наблюдений:

Азия/Калькутта не является действительным Parseable TimeZone, поэтому вам нужно немного механизм для получения соответствующего часового пояса.

8:00 также не является допустимым часовым поясом в java, поэтому вам нужно некоторый механизм для его форматирования в допустимом значении +08: 00

Сохраняя вышеуказанные моменты, следующий код сделает для вас нужным.

    SimpleDateFormat dateFormatTZGeneral = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
    SimpleDateFormat dateFormatTZISO = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX");
    SimpleDateFormat dateFormatWithoutTZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");


    String[][] zoneStrings = DateFormatSymbols.getInstance().getZoneStrings();

    Date date = null;

    String[] timeStampSplits = timestamp.split(" ");
    if(timeStampSplits.length>2) {

        String timezone = timeStampSplits[2];
        //First Case Asia/Calcutta
        if(Character.isAlphabetic(timezone.charAt(timezone.length()-1))) {

            for(String[] zoneString: zoneStrings) {
                if(zoneString[0].equalsIgnoreCase(timezone)) {
                    timeStampSplits[2] = zoneString[2];
                    break;
                }
            }

            timestamp = createString(timeStampSplits," ");
            date = getDate(timestamp, dateFormatTZGeneral);
        } else {
            //Second Case 8:00
            timeStampSplits[2] = formatTimeZone(timeStampSplits[2]);

            timestamp = createString(timeStampSplits," ");
            date = getDate(timestamp, dateFormatTZISO);
        }

    } else {
        // Third Case without timezone
        date = getDate(timestamp, dateFormatWithoutTZ);
    }

    System.out.println(date);

    TIMESTAMPTZ oraTimeStamp = new TIMESTAMPTZ(<connection object>,new java.sql.Timestamp(date.getTime());

Выше кода использует следующие методы утилиты

private static Date getDate(String timestamp, SimpleDateFormat dateFormat) {
    Date date = null;
    try {
        date = dateFormat.parse(timestamp);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return date;
}

private static String createString(String[] contents, String separator) {
    StringBuilder builder = new StringBuilder();
    for (String content : contents) {
        builder.append(content).append(separator);
    }
    builder.deleteCharAt(builder.length()-separator.length());

    return builder.toString();
}

private static String formatTimeZone(String timeZone) {
    String[] timeZoneSplits = timeZone.split(":");
    DecimalFormat formatter = new DecimalFormat("+##;-#");
    formatter.setMinimumIntegerDigits(2);

    timeZoneSplits[0] = formatter.format(Integer.parseInt(timeZoneSplits[0]));
    return createString(timeZoneSplits, ":");
}

Этот код специально написан для того, чтобы обслуживать ваши примеры временных меток, любое отклонение может не обрабатываться этим, и ему потребуется дополнительная настройка.

Надеюсь, это поможет вам.

Ответ 2

Вы должны проанализировать дату в соответствии с данными, поступающими в i.e dynamic. Для получения информации о том, какая константа используется андроидом, вы должны следовать ссылке и в случае Java вы должны следовать ссылка Вот фрагмент кода в другом формате Пример 1

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS zzzz");
    Date date = null;
    try {
        date = sdf.parse("2016-04-19 17:34:43.781 Pacific Standard Time");
        Log.e("date",""+date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    sdf.setTimeZone(TimeZone.getTimeZone("IST"));
    System.out.println(sdf.format(date));

Образец 2

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
    Date date = null;
    try {
        date = sdf.parse("2016-04-19 17:34:43.781 -08:00");
        Log.e("date",""+date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    sdf.setTimeZone(TimeZone.getTimeZone("IST"));
    System.out.println(sdf.format(date));

Образец 3

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    Date date = null;
    try {
        date = sdf.parse("2016-04-19 17:34:43.781");
        Log.e("date",""+date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    sdf.setTimeZone(TimeZone.getTimeZone("IST"));
    System.out.println(sdf.format(date));

Итак, в соответствии с этими тремя наборами образцов вы можете анализировать любой тип даты, кроме одного формата, т.е. "2016-04-19 17: 34: 43.781 Азия/Калькутта" в качестве часового пояса Азия/Калькутта или Азия/Бахрейн не может быть прочитан андроидом или java. Это формат, который поддерживается PHP в соответствии с моим пониманием. SO Если вы хотите разобрать этот тип формата, я думаю, вам нужно написать свой собственный SimpleDateFormat и определить этот контент и выполнить расчет в соответствии с вашими потребностями.

Ответ 3

Строки Timestamp находятся в другом формате,

 Ex-Here SimpleDateFormat uses pattern :
 'yyyy-MM-dd HH:mm:ss.SSS XXX'

where X is to represent timezone in [ISO 8601 time zone][1] format.For this      
timezone valid Timestamp Strings are (-08; -0800; -08:00).So,'Asia/Kolkata' 
will not be parsed for Sample 1.

There are three type of Timezone pattern to be assigned to SimpleDateFormat.
**'Z'** - RFC 822 time zone.
**'z'** - General time zone.
**'X'** - ISO 8601 time zone.

Таким образом, либо используйте разные SimpleDateFormat, либо конвертируйте Timezone всех временных меток в один и тот же шаблон часового пояса и используйте один SimpleDateFormat.