通过jsp执行时SQL语句不给出本地时间
Posted
技术标签:
【中文标题】通过jsp执行时SQL语句不给出本地时间【英文标题】:SQL statement does not give local time when execute through jsp 【发布时间】:2014-10-19 22:14:30 【问题描述】:当我从独立的 JDBC 程序对 SQLite JDBC 驱动程序执行 SQL 语句“SELECT datetime('now', 'localtime')”时,我得到正确的本地时间戳,而当我通过 JSP 页面执行它时,我得到格林威治标准时间/UTC 时间。有人可以解释为什么在 JSP 代码的情况下我会得到 UTC 时间吗?我想要由独立程序给出的当地时间。我确保两者都使用相同的 JDBC 驱动程序 jar 文件“sqlite-jdbc-3.7.2.jar”。
这是独立的 SQLite JDBC 程序:
import java.sql.*;
public class GetTimestamp
public static void main(String[] args)
Connection conn = null;
PreparedStatement p = null;
ResultSet rs = null;
try
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:C:/sqlite/db1", null, null);
p = conn.prepareStatement("SELECT datetime('now', 'localtime')");
rs = p.executeQuery();
System.out.println("Current timestamp = " + rs.getString(1));
conn.close();
catch (SQLException se)
System.out.println("Error: " + se.toString());
catch (ClassNotFoundException cnfe)
System.out.println("Error: " + cnfe.toString());
它的输出:
这是等效的 JSP:
<html>
<BODY>
<%@page import="java.sql.*"%>
<%
Connection conn = null;
PreparedStatement p = null;
ResultSet rs = null;
try
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:C:/sqlite/db1", null, null);
p = conn.prepareStatement("SELECT datetime('now', 'localtime')");
rs = p.executeQuery();
//System.out.println("Current timestamp = " + rs.getString(1));
out.println("Current timestamp = " + rs.getString(1));
conn.close();
catch (SQLException se)
//System.out.println("Error: " + se.toString());
out.println("Error: " + se.toString());
catch (ClassNotFoundException cnfe)
//System.out.println("Error: " + cnfe.toString());
out.println("Error: " + cnfe.toString());
%>
</BODY>
</HTML
它的输出是
【问题讨论】:
出于对代码的热爱,总是在finally
块中关闭您的 ResultSet、Statement/PreparedStatement 以及最后的 Connection。在 Java 6 及更高版本(在某些类上)可能不需要它,但它是最佳编程实践。
您是否尝试过使用rs.getDate
和SimpleDateFormat
?正如你所拥有的那样,你依赖于太多可能的变量。
布哈克辛迪,感谢您的建议。我提到的代码只是为了演示问题,而不是最终代码的一部分,它将处理您提到的问题。
OldCurmudgeon,我需要时间戳,而不仅仅是日期。我尝试了以下方法 rs.geTring(1) 是最接近的方法,只是它没有给出与 GMT 偏移 5.30 的时间: rs.getDate(1).toString() = 1970-01-01 rs.getTime(1 ).toString() = 05:30:00 rs.getTimestamp(1).toString() = 1970-01-01 05:30:00.0 rs.getString(1) = 2014-08-27 05:18:06
你用的是什么版本的 SQLLite?
【参考方案1】:
您可能需要设置时区?胡思乱想,希望对您有所帮助...
<fmt:setTimeZone value="GMT+10" /> //Set to whatever your timezone is
我不确定这是否有帮助。
【讨论】:
【参考方案2】:好吧,当我们在我们的脚本中使用隐式对象 out
时,它不会像 System.out 那样生成纯输出,因为它是 javax.servlet.jsp.JspWriter
的一种类型,所以它生成 HTML 而不是纯输出输出。
所以,有了这些信息,我假设这个对象正在以你不想要的方式包装你的信息。
您可能必须以另一种方式输出它,例如使用标签 setTimeZone 正如 Corey 所说,这是一个示例:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
<head>
<title>JSTL fmt:setTimeZone Tag</title>
</head>
<body>
<c:set var="now" value="<%=new java.util.Date()%>" />
<p>Date in Current Zone: <fmt:formatDate value="$now"
type="both" timeStyle="long" dateStyle="long" /></p>
<p>Change Time Zone to GMT-8</p>
<fmt:setTimeZone value="GMT-8" />
<p>Date in Changed Zone: <fmt:formatDate value="$now"
type="both" timeStyle="long" dateStyle="long" /></p>
</body>
</html>
【讨论】:
Bruno,我将 String 对象传递给 out.println() 方法,因此该方法不太可能知道传递的 String 对象是否是时间戳/日期时间对象。我不在我的 JSP 页面中使用像“c:set”这样的标签。当我尝试您的代码时,没有值显示为部分标记。为了使您的代码正常工作,我是否需要安装其他东西以及 Tomcat Web 服务器?
我正在寻找不使用 taglibs 的解决方案。一些建议使用 Tomcat 配置工具或直接编辑 windows 注册表为 Java 设置时区环境变量。但到目前为止还没有运气。【参考方案3】:从我从这个thread 中读到的内容。 SQLLite 没有Date type,所以需要使用rs.getString(1);
获取它的String
试试这个。
<%
Connection conn = null;
PreparedStatement p = null;
ResultSet rs = null;
try
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:C:/sqlite/db1", null, null);
p = conn.prepareStatement("SELECT datetime('now', 'localtime')");
rs = p.executeQuery();
//System.out.println("Current timestamp = " + rs.getString(1));
DateFormat converter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date queryDate = converter.parse(rs.getString(1));
out.println("Current timestamp = " + converter.format(queryDate));
conn.close();
catch (SQLException se)
//System.out.println("Error: " + se.toString());
out.println("Error: " + se.toString());
catch (ClassNotFoundException cnfe)
//System.out.println("Error: " + cnfe.toString());
out.println("Error: " + cnfe.toString());
catch(ParseException e)
out.println("ParseError: " + e.toString());
%>
不确定这是否有帮助。
【讨论】:
只要对你有帮助就没有问题。【参考方案4】:最后,我根据大家的意见想出了一个解决方法。基本上,它获取时区信息,获取其偏移量,将偏移量添加到从 SQLite 查询的时间戳值。 当然,当 SQLite JDBC 驱动程序将来开始提供正确的值时,变通方法会有一点危险!
<HTML>
<BODY>
<%@page import="java.sql.*"%>
<%@page import="java.util.*"%>
<%@page import="java.text.*"%>
<%
Connection conn = null;
PreparedStatement p = null;
ResultSet rs = null;
// Get current timezone and find offset from UTC.
TimeZone timeZone = TimeZone.getDefault();
out.println("<BR>Current timezone=" + timeZone);
long offset = timeZone.getOffset(System.currentTimeMillis());
out.println("<BR>Timezone offset=" + offset);
try
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:C:/sqlite/db1", null, null);
p = conn.prepareStatement("SELECT datetime('now', 'localtime')");
rs = p.executeQuery();
// Convert queried timestamp to Java Date object.
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date queryDate = sdf.parse(rs.getString(1));
out.println("<BR>timestamp from SQLite = " + sdf.format(queryDate));
// Get localtime by adding time zone offset.
long tm = queryDate.getTime() + offset; // New time with offset.
java.util.Date newDate = new java.util.Date(tm);
out.println("<BR>timestamp with timezone offset= " + sdf.format(newDate));
rs.close();
conn.close();
catch (SQLException se)
//System.out.println("Error: " + se.toString());
out.println("Error: " + se.toString());
catch (ClassNotFoundException cnfe)
//System.out.println("Error: " + cnfe.toString());
out.println("Error: " + cnfe.toString());
%>
</BODY>
</HTML>
这里是 o/p:
【讨论】:
以上是关于通过jsp执行时SQL语句不给出本地时间的主要内容,如果未能解决你的问题,请参考以下文章