3

我的应用程序需要以下内容。

在我的应用程序中(在 struts 中),我们需要支持波斯日历。

当我们提交表单时,日期在 Action 类中以 String 的形式出现。我们需要将此日期以波斯格式保存在数据库中。我们已经为波斯日历配置了数据库。在从数据库用户检索数据时,应该只能看到波斯格式的日期。

此外,用户可以切换 2 种语言(英语、波斯语)。所以,应用程序应该支持两种类型的日历(公历和波斯)。如果用户用英语登录,公历应该是可见的。如果用户以波斯语登录,那么波斯日历应该是可见的。

对于从公历到波斯的日期转换,我在下面使用: http ://www.dailyfreecode.com/forum/converter-gregorian-date-jalali-date-20288.aspx

在上述要求中,我面临两个问题:

  1. 提交表单时,我们如何在数据库中以波斯格式保存日期(在 Action 类中为 String 格式)?
  2. 从数据库中检索数据时,它应该采用波斯格式。截至目前,JDBC 客户端正在检索公历日历中的日期。

我正在传递 java.sql.Date(today's date),它以波斯格式保存在数据库中。使用下面的代码。

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 客户端中是否有任何设置可以将从数据库返回的日期转换为波斯格式本身(就像我们在 Oracle 中有 NLS_CALENDAR ,NLS_DATE_FORMAT 一样)?

对于第一个问题,如果我以波斯格式传递日期,那么在 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();

以上是在 DB 中插入为 0777/09/13。

我们如何才能克服上述问题?提前致谢。

4

4 回答 4

2

没有日历类型,java.sql.Date因此不可能将其强制为波斯语。JDBC 中的所有日期/时间值都以中性形式标准化,Oracle 数据库也使用中性形式进行存储和处理。当NLS_CALENDAR是波斯语时,Oracle 将值转换为中性形式和从中性形式转换,它只是在波斯日历约定中“呈现”它,而它在内部以中性形式处理。

通常,对后端中的所有值一致地使用中性形式是最佳的。通常在 UI 层中使用转换器作为本地化的一部分,以根据个人用户的首选语言环境进行定制。如果需要在中间层使用 Java 进行本地化,java.time.chrono那么 Douglas 在上面建议的包将是一个干净的解决方案。

于 2020-07-30T19:24:02.693 回答
1

提交表单时,我们如何在数据库中以波斯格式保存日期(在 Action 类中为 String 格式)?

将日期存储为DATE数据类型,当您要将其插入表中时,请使用TO_DATE波斯语的 NLS 日历参数将其从 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 |

从数据库中检索数据时,它应该采用波斯格式。截至目前,JDBC 客户端正在检索公历日历中的日期。

输出值时,只需指定要用于格式化它的日历。因此,对于波斯语,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 客户端以波斯格式检索日期。

这是一个普遍的误解。存储在 Oracle 表中的DATE数据类型为 7 个字节,包含年(2 个字节)、月、日、小时、分钟和秒(每个 1 个字节)。它没有任何“格式”(但它有效地存储在公历中)。

JDBC 不传输格式化的日期,它只是传输这 7 个字节并将其存储在一个java.sql.Date类中(该类也只存储这些字节)。

如果要格式化DATE数据类型,则需要将其转换为另一种数据类型;通常是您要TO_CHAR在 Oracle 数据库中使用的字符串(或其他一些在 Java 中格式化日期的方法)。

于 2018-04-25T13:20:01.103 回答
0

java.sql.Date被定义为UTC,即公历。从数据库中获取 DATE 作为 ajava.sql.Date不太可能做任何有用的事情。正确的答案是定义一个PersianChronologywhich extendsjava.time.chrono.AbstractChronologyPersianLocalDatewhich implements java.time.chrono.ChronoLocalDate。然后从数据库中获取值作为PersianLocalDate. 这是很多工作,但理论上这是正确的做法。

PersianLocalDate per = rs.getObject(col, PersianLocalDate.class);

我认为这可以发挥作用。不容易,但可能。如果您的PersianLocalDate班级定义了以下方法

public static PersianLocalDate of(oracle.sql.DATE date) { ... }

然后 Oracle 数据库 JDBC 将使用该方法PersianLocalDate在上面的getObject调用中构造一个。有趣的部分是实现该of(DATE)方法。所有oracle.sql.DATE方法都假定为公历。最好的办法是自己调用DATE.getBytes和解释字节。字节 0 和 1 是年份,2 是月份,3 是月份中的日期。TIMESTAMP.getJavaYear会将这两个字节转换为 int 年份。它对日历一无所知;它只是在做算术。根据数据库在发送波斯 DATE 作为查询结果时所做的事情,应该让您构造一个PersianLocalDate. 如果数据库正在转换为公历,则您必须转换回波斯语。您PersianChronology应该对此有所帮助。

反过来,将 a 发送PersianLocalDate到数据库会更有趣。ofOracle 数据库 JDBC 驱动程序无法将未知类转换为像 DATE 这样的数据库类型,与上述方法挂钩没有任何功能。您可以尝试制作PersianLocalDateextend oracle.sql.ORAData。该toDatum方法必须返回oracle.sql.DATE与数据库作为查询结果发送的相同字节。

也许更简单的方法是将波斯日期作为 VARCHAR/字符串来回发送到数据库。驱动程序会调用一个static of(String)方法,PersianLocalDate因此PersianLocalDate很容易获得一个。如果数据库对PersianLocalDate.toString结果做了正确的事情,那么调用 setString 可以轻松发送值。如果没有,则PersianLocalDate.toDatabaseString自己定义并进行转换。

这是我们在实施支持时谈到的一个用例,java.time但我们根本没有做任何事情所需的资源。而且我们不知道它有多普遍,所以很难证明做这项工作的合理性。如果您有支持合同,我鼓励您提交 SR 并请求增强请求。如果你能提供一个PersianChronologyPersianLocalDate我会更容易获得分配一些资源来做某事。也许只不过是一个使 setObject 工作的钩子,但至少如此。我希望我能提供更多帮助。

于 2020-07-24T19:05:41.677 回答
0

只是为那些仍在寻找如何在应用程序中实现波斯日历的人提供输入。

我的应用程序应该支持公历和波斯历,还应该支持 Oracle 和 PostgreSQL 数据库。

要以最少的努力实施波斯历,请执行以下步骤:

  1. 使用以下链接http://www.dailyfreecode.com/forum/converter-gregorian-date-jalali-date-20288.aspx中建议的实现将来自 UI 的每个日期转换为 validate() 形式的公历格式

  2. 一旦日期转换为公历,整个应用程序将继续运行,因为它之前使用公历日期运行。

  3. 在将日期保存在数据库中时,我决定仅以公历格式存储日期,因为我还需要支持 PostgreSQL 数据库并且它不支持波斯日历。

  4. 在将数据提取到 UI 时,将从 DB 中检索日期,然后我再次将日期转换为波斯格式。

要在 UI 上显示波斯日历,请参阅以下链接。它还有其他日历实现 http://keith-wood.name/calendars.html

上述方法可以帮助实现大多数不同的日历。

于 2020-07-18T16:26:59.993 回答