我的应用程序需要以下内容。
在我的应用程序(在支撑杆中(中,我们需要支持波斯日历。
当我们提交表格时,日期将作为字符串在动作类中。我们需要将该日期保存在DB中。我们为波斯日历配置了DB。而且,从DB用户检索数据时,应仅以波斯语格式查看日期。
另外,用户可以用两种语言切换(英语,波斯语(。因此,应用程序应支持这两种类型的日历(Gregorian和Persian(。如果用户登录英语,则应可见Gregorian日历。如果用户登录波斯语,则应可见波斯日历。
对于从格里高利(Gregorian(到波斯语的日期转换,我正在使用以下:http://www.dailyfreecode.com/forum/converter-gregorian-date-jalali-date-date-20288.aspx
在上述要求中,我面临2个问题:
- 在提交表单时,我们如何以DB格式保存日期(在行动类中以字符串格式为字符串格式(?
- 在从数据库中检索数据时,应以波斯语格式出现。截至目前,JDBC客户端正在检索Gregorian Calender的日期。
我正在通过java.sql.date(今天的日期(,它以DB中的波斯格式保存。使用以下代码。
java.sql.Date sqlDate = null;
java.util.Date utilDate = new Date();
sqlDate = new java.sql.Date(utilDate.getTime());
PreparedStatement psmtInsert = conn.prepareStatement(insertQuery);
psmtInsert.setDate(1, sqlDate));
psmtInsert.executeUpdate();
检索:
PreparedStatement psmtSelect = conn.prepareStatement("select dateOfJoining from EMPLOYEE");
ResultSet resultSet = psmtSelect.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getDate(1));
}
,但它是格里高利类型的返回日期。
我们是否在tomcat/jvm/jdbc client中有任何设置,它将从db返回的日期转换为波斯格式本身(就像我们有nls_calendar,nls_date_format in Oracle中的nls_calendar(?
对于第一期,如果我以波斯语格式传递日期,则在db中会保存错误。PFB我的代码:
java.sql.Date sqlDate = null;
java.util.Date utilDate = new Date("1397/02/04");
sqlDate = new java.sql.Date(utilDate.getTime());
PreparedStatement psmtInsert = conn.prepareStatement(insertQuery);
psmtInsert.setDate(1, sqlDate));
psmtInsert.executeUpdate();
上面的插入为0777/09/13 in db。
我们如何克服上述问题?预先感谢。
java.sql.Date
中没有日历类型,因此不可能将其强加于 persian 。JDBC中的所有日期/时间值以中性形式进行了归一化,Oracle数据库也使用中性形式以及存储和处理。当NLS_CALENDAR
是波斯语时,Oracle会转换为中性形式的值,这是"呈现"它在内部中性形式处理时在波斯日历大会中。
通常,将中性形式始终用于后端中的所有值是最佳的。通常,在UI层中使用转换器作为本地化的一部分,以量身定制为单个用户的首选语言环境。如果需要在中间层中的Java进行定位,则道格拉斯建议的java.time.chrono
软件包将是一个干净的解决方案。
在提交表单时,如何以DB格式保存日期(在行动类中以字符串格式为字符串格式(?
将日期存储为DATE
数据类型,当您将其插入表中时,将其与nls Calendar参数一起使用Persion格式的字符串将其转换为日期:
sql小提琴
查询1 :
SELECT TO_DATE(
'1397/02/05',
'yyyy/mm/dd',
'nls_calendar=persian'
)
FROM DUAL
结果:
| TO_DATE('1397/02/05','YYYY/MM/DD','NLS_CALENDAR=PERSIAN') |
|-----------------------------------------------------------|
| 2018-04-25T00:00:00Z |
从DB中检索数据时,应以波斯语格式出现。截至目前,JDBC客户端正在检索Gregorian Calender的日期。
输出值时,只需指定要使用的日历以格式化它即可。因此,对于波斯语,将TO_CHAR
与NLS日历参数用于波斯语:
查询2 :
SELECT TO_CHAR(
DATE '2018-04-25',
'yyyy/mm/dd',
'nls_calendar=persian'
)
FROM DUAL
结果:
| TO_CHAR(DATE'2018-04-25','YYYY/MM/DD','NLS_CALENDAR=PERSIAN') |
|---------------------------------------------------------------|
| 1397/02/05 |
我们有任何方法使用JDBC客户端以波斯语格式检索日期。
这是一个常见的误解。DATE
数据类型存储在Oracle表中为7个字节,其中包含年度(2个字节(,月,天,小时,分钟,分钟和秒(每个字节1个(。它没有任何"格式"(但有效地存储在Gregorian日历中(。
JDBC不传输格式的日期,它只是将这些7个字节传输并将其存储在java.sql.Date
类中(也只是存储这些字节(。
如果要格式化DATE
数据类型,则需要将其转换为另一种数据类型;通常是要在Oracle数据库中使用TO_CHAR
的字符串(或在Java中格式化日期的其他方法(。
只是为那些仍在寻找如何在应用程序中实现波斯日历的人提供输入。
我的应用程序应支持Gregorian和Persian日历,也应支持Oracle和Postgresql DB。
以最低限度的努力执行以下步骤:
-
使用以下链接中建议的实现将从UI从UI转换为validate((的Gregorian格式http://www.dailyfreecode.com/forum/converter-gregorian-date-jalali-date-date-20288.aspx
-
一旦将日期转换为Gregorian,整个应用程序将继续运行,因为它在Gregorian Date的早期运行时将继续运行。
-
在将日期保存到DB中时,我决定仅以Gregorian格式存储日期,因为我还需要支持PostgreSQL DB,并且不支持波斯日历。
-
在将数据获取到UI时,将从DB中检索日期,并且我再次以波斯的格式转换日期。
要在UI上显示波斯日历,请参阅下面的链接。它还有其他日历实现http://keith-wood.name/calendars.html
上述方法可以帮助实现大多数不同的日历。
java.sql.Date
定义为在Gregorian的UTC中。从数据库中获得java.sql.Date
的日期不太可能做任何有用的事情。正确的答案是定义PersianChronology
,该CC_13扩展了java.time.chrono.AbstractChronology
和PersianLocalDate
的java.time.chrono.ChronoLocalDate
。然后从数据库中获取PersianLocalDate
的值。这是很多工作,但从理论上讲,这是正确的事情。
PersianLocalDate per = rs.getObject(col, PersianLocalDate.class);
我认为这可以使其工作。不容易,但可能。如果您的PersianLocalDate
类定义以下方法
public static PersianLocalDate of(oracle.sql.DATE date) { ... }
然后,Oracle数据库JDBC将使用该方法在上面的getObject
调用中构造PersianLocalDate
。有趣的部分将是实现of(DATE)
方法。所有oracle.sql.DATE
方法都假设一个Gregorian日历。最好的选择是致电DATE.getBytes
并自己解释字节。字节0和1是一年,第2个是一个月,3个是本月的一天。TIMESTAMP.getJavaYear
将将这两个字节转换为INT年。它对日历一无所知;只是在做算术。取决于数据库在发送波斯日期作为查询结果时所做的事情,该结果应该让您构建PersianLocalDate
。如果数据库转换为Gregorian,则必须转换回波斯语。您的PersianChronology
应该有所帮助。
以另一种方式走,将PersianLocalDate
发送到数据库将变得更加有趣。Oracle数据库JDBC驱动程序没有能力将未知类转换为诸如日期之类的数据库类型,没有等于上述of
方法。您可以尝试使PersianLocalDate
扩展oracle.sql.ORAData
。toDatum
方法必须以与数据库作为查询结果相同的字节返回oracle.sql.DATE
。
也许一种简单的方法是将波斯的日期来回发送到数据库作为Varchars/字符串。驱动程序将在PersianLocalDate
上调用static of(String)
方法,因此获得PersianLocalDate
很容易。如果数据库对PersianLocalDate.toString
结果做正确的事情,则调用setString使发送值的发送使其变得容易。如果不是,则定义PersianLocalDate.toDatabaseString
并自己进行转换。
这是我们在实施java.time
支持时谈论的用例,但我们根本没有任何做任何事情所需的资源。而且我们不知道这将有多普遍,所以很难证明做这项工作是合理的。如果您有支持合同,我鼓励您提交SR并要求提高请求。如果您可以提供PersianChronology
和PersianLocalDate
,那么我更容易获得分配的资源来做某事。也许只不过是一个使setObject起作用的钩子,但至少这就是钩子。我希望我能提供更多的帮助。