JSP 日期处理
java.time 在页面上的格式化、JSTL fmt 标签、时区处理。
Key Points页面里格式化日期优先用 <fmt:formatDate> 或 DateTimeFormatter,不要用已过时的 SimpleDateFormat。
脚本写法
JSP
<%@ page import="java.time.*, java.time.format.DateTimeFormatter" %>
<%
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
%>
<p>现在:<%= now.format(fmt) %></p>
<p>日期:<%= LocalDate.now() %></p>
<p>时间戳:<%= Instant.now().toEpochMilli() %></p>Output
现在:2026-11-03 14:25:09
日期:2026-11-03
时间戳:1793696709418JSTL fmt 标签
JSP
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<jsp:useBean id="now" class="java.util.Date"/>
<p><fmt:formatDate value="${now}" pattern="yyyy-MM-dd"/></p>
<p><fmt:formatDate value="${now}" pattern="yyyy年M月d日 HH:mm"/></p>
<p><fmt:formatDate value="${now}" type="both" dateStyle="long" timeStyle="short"/></p>Output
2026-11-03
2026年11月3日 14:25
2026年11月3日 下午2:25<fmt:formatDate> accepts only java.util.Date. Convert first with Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()), or convert in the controller before putting it into the request.
时区
JSP
<fmt:setTimeZone value="Asia/Shanghai"/>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss z"/>
<fmt:timeZone value="UTC">
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss z"/>
</fmt:timeZone>Output
2026-11-03 14:25:09 CST
2026-11-03 06:25:09 UTC相对时间
JSP
<%@ taglib prefix="fn" uri="jakarta.tags.functions" %>
<%
long diff = (System.currentTimeMillis()
- ((java.util.Date) request.getAttribute("created")).getTime()) / 1000;
String rel;
if (diff < 60) rel = diff + " 秒前";
else if (diff < 3600) rel = (diff / 60) + " 分钟前";
else if (diff < 86400) rel = (diff / 3600) + " 小时前";
else rel = (diff / 86400) + " 天前";
%>
<span title="<fmt:formatDate value="${created}" pattern="yyyy-MM-dd HH:mm"/>"><%= rel %></span>A relative timestamp reads better in a list than an absolute one, but hovering must reveal the exact time or users cannot place it.
SimpleDateFormat is not thread-safe. Sharing one declared in <%! %> produces wrong dates under concurrency — a bug that is nearly impossible to reproduce. DateTimeFormatter has no such problem.脚本写法
JSP
<%@ page import="java.time.*, java.time.format.DateTimeFormatter" %>
<%
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
%>
<p>现在:<%= now.format(fmt) %></p>
<p>日期:<%= LocalDate.now() %></p>
<p>时间戳:<%= Instant.now().toEpochMilli() %></p>Output
现在:2026-11-03 14:25:09
日期:2026-11-03
时间戳:1793696709418JSTL fmt 标签
JSP
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<jsp:useBean id="now" class="java.util.Date"/>
<p><fmt:formatDate value="${now}" pattern="yyyy-MM-dd"/></p>
<p><fmt:formatDate value="${now}" pattern="yyyy年M月d日 HH:mm"/></p>
<p><fmt:formatDate value="${now}" type="both" dateStyle="long" timeStyle="short"/></p>Output
2026-11-03
2026年11月3日 14:25
2026年11月3日 下午2:25<fmt:formatDate> 只接受 java.util.Date。LocalDateTime 要先转:Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()),或者在 Controller 里就转好再放进 request。
时区
JSP
<fmt:setTimeZone value="Asia/Shanghai"/>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss z"/>
<fmt:timeZone value="UTC">
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss z"/>
</fmt:timeZone>Output
2026-11-03 14:25:09 CST
2026-11-03 06:25:09 UTC相对时间
JSP
<%@ taglib prefix="fn" uri="jakarta.tags.functions" %>
<%
long diff = (System.currentTimeMillis()
- ((java.util.Date) request.getAttribute("created")).getTime()) / 1000;
String rel;
if (diff < 60) rel = diff + " 秒前";
else if (diff < 3600) rel = (diff / 60) + " 分钟前";
else if (diff < 86400) rel = (diff / 3600) + " 小时前";
else rel = (diff / 86400) + " 天前";
%>
<span title="<fmt:formatDate value="${created}" pattern="yyyy-MM-dd HH:mm"/>"><%= rel %></span>列表页显示「3 分钟前」比「2026-11-03 14:22:01」更易读,但鼠标悬停要能看到精确时间——否则用户没法判断具体是什么时候。
SimpleDateFormat 不是线程安全的。在 <%! %> 里声明一个共享的 SimpleDateFormat 并复用,高并发下会解析出错乱日期——这类 bug 极难复现,直接用 DateTimeFormatter 就没有这个问题。