【问题标题】:SQL statement does not give local time when execute through jsp通过jsp执行时SQL语句不给出本地时间
【发布时间】: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.getDateSimpleDateFormat?正如你所拥有的那样,你依赖于太多可能的变量。
  • 布哈克辛迪,感谢您的建议。我提到的代码只是为了演示问题,而不是最终代码的一部分,它将处理您提到的问题。
  • 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?

标签: java sql sqlite jsp jdbc


【解决方案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:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 2013-04-24
      • 2017-10-20
      • 1970-01-01
      • 2013-08-18
      • 1970-01-01
      相关资源
      最近更新 更多