com.mysql.jdbc.PreparedStatement setDate:无法保持预感格里高利历日期(1582年10月15日之前的日期)

时间:2014-05-10 18:30:06

标签: java mysql hibernate date gregorian-calendar

(抱歉我的英文...)

为了表示1582年10月15日(格里高利历的开始日期)之前的格里历日历,可以使用一个预知的GregorianCalendar。这样的日历允许使用格里高利历系统表示1582年10月15日之前的日期,如果它当时不存在的话。 创建一个新的预防GregorianCalendar的两种可能的方法如下(我报告这个用于测试目的,但它不是必需的):

    GregorianCalendar proleptic = null;

    proleptic = new GregorianCalendar();
    proleptic.clear(); 
    proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
    proleptic.set(Calendar.DAY_OF_MONTH, 8);
    proleptic.set(Calendar.MONTH, Calendar.OCTOBER);
    proleptic.set(Calendar.YEAR, 1582);
    System.out.println("proleptic_calendar_8Oct1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"], in millis ["+proleptic.getTimeInMillis()+"]");


    GregorianCalendar prolepticFromXML = null;
    String newDate = "1582-10-08";
    DatatypeFactory datatypeFactory = null;
    try {
        datatypeFactory = DatatypeFactory.newInstance();
        prolepticFromXML = datatypeFactory.newXMLGregorianCalendar(newDate).toGregorianCalendar();
    } catch (Exception e) {
        e.printStackTrace();
    } 
    System.out.println("prolepticFromXML_8Oct1582 [DAY_OF_MONTH ["+prolepticFromXML.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+prolepticFromXML.get(Calendar.MONTH)+"], YEAR ["+prolepticFromXML.get(Calendar.YEAR)+"], in millis ["+prolepticFromXML.getTimeInMillis()+"]");

    System.out.println("millis matches: ["+(proleptic.getTimeInMillis() == prolepticFromXML.getTimeInMillis())+"]

输出:

proleptic_calendar_8Oct1582 [DAY_OF_MONTH [8], MONTH [9], YEAR [1582], in millis [-12219901200000]
prolepticFromXML_8Oct1582 [DAY_OF_MONTH [8], MONTH [9], YEAR [1582], in millis [-12219901200000]
millis matches: [true]

现在我们想象从输入源(网络表单,肥皂请求等)接收一个字符串,并用它构建一个预知的GregorianCalendar,我们可以称之为 myCalendarField ,. 然后,我想在一个类型为DATE的列中的mysql数据库上写这个日期。 我使用 Hibernate 作为持久性框架,并想象 myCalendarField 是映射到实体类的字段

@Temporal(TemporalType.DATE)
@Column(name = "a_test_date_field")
public Calendar getMyCalendarField() {
    return this.myCalendarField;
}

在org.hibernate.type.CalendarDateType开始的代码之后,管理java Calendar和sql DATE之间的映射,我发现它调用了方法

public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
com.mysql.jdbc.PreparedStatement 中的

,可在mysql连接器中找到,

传递

new java.sql.Date( myCalendarField.getTime().getTime() ); 

as x

现在,setDate方法使用SimpleDateFormat来转换字符串中传递的Date,然后在byte []上转换此字符串并跟随工作流。 要格式化连接器的日期,请执行以下操作:

SimpleDateFormat ddf = new SimpleDateFormat("''yyyy-MM-dd''", Locale.US);
ddf.setTimeZone(cal.getTimeZone()); 
String timeString = ddf.format(x);

此时java.text.SimpleDateFormat的format方法做了类似这样的事情

Calendar calendar = null;
calendar = Calendar.getInstance(TimeZone.getDefault(), Locale.US);
calendar.setTime(x);

并使用新的实例化日历获取所有日期和时间信息以构建输出格式化字符串。 然后,新创建的日历不再是预感,而是将1582年10月15日之前的日期转换为朱利安日期。 因此,我们在DB上获得的日期与输入中收到的日期不同。

因此,如果一个java Web应用程序收到例如8 oct 1582,将其视为一个preleptic Gregorian Calendar并希望将其保存在mysql DB上的DATE字段中,该日期将持续到1592年9月28日。 目前我没有办法在没有修改的情况下坚持原始输入日期。

我的结论是否正确?您是否知道使用Java + Hibernate +我的sql连接器在1582年10月15日之前将mySql DB保留为具有预防性的GregorianCalendar的任何方法?

0 个答案:

没有答案