Другое

Как добавить дни к дате в JSP - Полное руководство

Узнайте несколько методов добавления дней к датам в JSP, включая класс Calendar, выражения EL и API Java 8 Date-Time. Рассчитывайте даты платежей с практическими примерами и лучшими практиками.

Как добавить n дней к дате в JSP?

У меня есть следующий код JSP, который отображает дату оплаты:

jsp
<li>Paid Due Date: <fmt:formatDate value="${premiumPaidToDate.time}"
                                    pattern="dd/MM/yyyy"/></li>

Мне также нужно отобразить следующую дату оплаты, которая должна быть через 10 дней после текущей даты оплаты. Как можно добавить 10 дней к значению premiumPaidToDate.time в JSP?

Чтобы добавить n дней к дате в JSP, можно использовать Java класс Calendar внутри скриптлетов или применить JSTL с арифметикой времени. Для вашего конкретного случая добавления 10 дней к premiumPaidToDate.time, наиболее надежным подходом является использование метода Calendar.add() в скриптлетах, а затем форматирование результата с помощью тега JSTL fmt:formatDate.

Содержание

Использование класса Calendar в скриптлетах

Наиболее прямой и надежный метод - использование Java класса Calendar внутри скриптлетов. Этот подход обеспечивает полный контроль над манипуляциями с датами и обрабатывает крайние случаи, такие как переходы между месяцами.

jsp
<%@ page import="java.util.*,java.text.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!-- Отображение текущей даты платежа -->
<li>Дата оплаты: <fmt:formatDate value="${premiumPaidToDate.time}"
                                    pattern="dd/MM/yyyy"/></li>

<!-- Расчет даты следующего платежа (через 10 дней) -->
<%
java.util.Calendar cal = java.util.Calendar.getInstance();
cal.setTime((java.util.Date) pageContext.getAttribute("premiumPaidToDate"));
cal.add(java.util.Calendar.DAY_OF_MONTH, 10);
pageContext.setAttribute("nextPaymentDate", cal.getTime());
%>

<!-- Отображение даты следующего платежа -->
<li>Дата следующего платежа: <fmt:formatDate value="${nextPaymentDate}"
                                        pattern="dd/MM/yyyy"/></li>

Основные преимущества этого подхода:

  • Автоматическая обработка переходов между месяцами и годами
  • Потокобезопасность при правильном использовании
  • Хорошо документированный и широко поддерживаемый
  • Автоматическая обработка летнего времени

Распространенные константы Calendar для манипуляций с датами:

  • Calendar.DAY_OF_MONTH - добавление дней
  • Calendar.DAY_OF_YEAR - добавление дней (с учетом года)
  • Calendar.WEEK_OF_YEAR - добавление недель
  • Calendar.MONTH - добавление месяцев
  • Calendar.YEAR - добавление лет

Примечание: Согласно документации Java Calendar, метод add() автоматически обрабатывает переполнение полей. Например, добавление 10 дней к 25 января правильно приведет к 4 февраля.

Арифметика времени с выражениями EL

Также можно выполнять простую арифметику дат с помощью выражений EL, работая напрямую с метками времени. Этот метод менее гибкий, но хорошо подходит для простых случаев.

jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!-- Простой подход: добавление миллисекунд напрямую -->
<c:set var="nextPaymentTime" value="${premiumPaidToDate.time + (10 * 24 * 60 * 60 * 1000)}"/>
<c:set var="nextPaymentDate" value="${new java.util.Date(nextPaymentTime)}"/>

<!-- Отображение дат -->
<li>Дата оплаты: <fmt:formatDate value="${premiumPaidToDate.time}"
                                    pattern="dd/MM/yyyy"/></li>
<li>Дата следующего платежа: <fmt:formatDate value="${nextPaymentDate}"
                                        pattern="dd/MM/yyyy"/></li>

Разбор расчета:

  • 1 день = 24 часа × 60 минут × 60 секунд × 1000 миллисекунд
  • 10 дней = 10 × 24 × 60 × 60 × 1000 = 864,000,000 миллисекунд

Ограничения:

  • Не обрабатывает изменения летнего времени
  • Нет автоматической обработки переходов между месяцами и годами
  • Менее читабельно и сложнее в поддержке

Как показано в исследованиях блога Small Concepts, этот подход работает для простых сценариев, но может быть ненадежным для производственных приложений.

JSTL с пользовательскими функциями

Для более сложных манипуляций с датами в JSTL можно создавать пользовательские функции. Этот подход обеспечивает лучшее разделение ответственности и возможность повторного использования.

Сначала создайте библиотеку пользовательских функций (WEB-INF/tags/functions.tld):

xml
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
    
    <description>Библиотека функций для операций с датами</description>
    <display-name>functions</display-name>
    <tlib-version>1.1</tlib-version>
    <short-name>xfn</short-name>
    <uri>http://yourdomain/functions</uri>
    
    <function>
        <description>Добавляет указанное количество дней к дате</description>
        <name>addDays</name>
        <function-class>com.yourpackage.DateFunctions</function-class>
        <function-signature>java.util.Date addDays(java.util.Date, int)</function-signature>
    </function>
</taglib>

Создайте класс функции (com.yourpackage.DateFunctions.java):

java
package com.yourpackage;

import java.util.Calendar;
import java.util.Date;

public class DateFunctions {
    public static Date addDays(Date date, int days) {
        if (date == null) return null;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, days);
        return cal.getTime();
    }
}

Использование в JSP:

jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://yourdomain/functions" prefix="xfn" %>

<li>Дата оплаты: <fmt:formatDate value="${premiumPaidToDate.time}"
                                    pattern="dd/MM/yyyy"/></li>
<li>Дата следующего платежа: <fmt:formatDate value="${xfn:addDays(premiumPaidToDate, 10)}"
                                        pattern="dd/MM/yyyy"/></li>

Этот подход обеспечивает чистый, повторно используемый код и соответствует лучшим практикам разработки JSP.

Подход с использованием API даты и времени Java 8

Для современных Java-приложений рекомендуется использовать API даты и времени Java 8, который предлагает лучший дизайн и потокобезопасность.

jsp
<%@ page import="java.time.*,java.time.format.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!-- Преобразование Date в LocalDate и добавление дней -->
<%
java.util.Date originalDate = (java.util.Date) pageContext.getAttribute("premiumPaidToDate");
Instant instant = originalDate.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDate localDate = instant.atZone(zoneId).toLocalDate();
LocalDate nextPaymentDate = localDate.plusDays(10);
pageContext.setAttribute("nextPaymentLocalDate", nextPaymentDate);
%>

<!-- Отображение дат -->
<li>Дата оплаты: <fmt:formatDate value="${premiumPaidToDate.time}"
                                    pattern="dd/MM/yyyy"/></li>
<li>Дата следующего платежа: <fmt:formatDate value="${nextPaymentLocalDate}"
                                        type="date" pattern="dd/MM/yyyy"/></li>

Преимущества API даты и времени Java 8:

  • Неизменяемые объекты (потокобезопасные)
  • Лучший API дизайн
  • Более четкое разделение ответственности
  • Поддержка разных часовых поясов

Лучшие практики и рекомендации

  1. Предпочитайте класс Calendar для общего использования: Наиболее надежный и обрабатывающий крайние случаи
  2. Рассмотрите возможность переноса логики в сервлеты: Для сложных расчетов используйте бизнес-логический слой
  3. Используйте правильные импорты: Всегда импортируйте необходимые Java классы вверху JSP
  4. Обрабатывайте нулевые значения: Добавляйте проверки на null для избежания NullPointerException
  5. Учитывайте производительность: Для приложений с высокой нагрузкой минимизируйте использование скриптлетов

Экспертное мнение с форума Coderanch: “Пусть сервлет выполняет этот расчет, а затем перенаправляет запрос в JSP” - это разделяет бизнес-логику от представлений.

Полный пример реализации

Вот полный, готовый к производству пример:

jsp
<%@ page import="java.util.*,java.text.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%-- Логика расчета даты --%>
<%
try {
    if (premiumPaidToDate != null) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime((java.util.Date) premiumPaidToDate);
        cal.add(java.util.Calendar.DAY_OF_MONTH, 10);
        pageContext.setAttribute("nextPaymentDate", cal.getTime());
    }
} catch (Exception e) {
    // Обработка ошибки
    pageContext.setAttribute("nextPaymentDate", null);
}
%>

<div class="payment-dates">
    <h3>График платежей</h3>
    
    <ul>
        <li>
            <strong>Дата оплаты:</strong>
            <c:if test="${not empty premiumPaidToDate}">
                <fmt:formatDate value="${premiumPaidToDate.time}"
                               pattern="dd/MM/yyyy HH:mm"/>
            </c:if>
            <c:if test="${empty premiumPaidToDate}">
                Недоступно
            </c:if>
        </li>
        
        <li>
            <strong>Дата следующего платежа:</strong>
            <c:if test="${not empty nextPaymentDate}">
                <fmt:formatDate value="${nextPaymentDate}"
                               pattern="dd/MM/yyyy HH:mm"/>
            </c:if>
            <c:if test="${empty nextPaymentDate}">
                Недоступно
            </c:if>
        </li>
    </ul>
    
    <c:if test="${not empty nextPaymentDate}">
        <p class="payment-note">
            Следующий платеж должен быть произведен через ${xfn:daysBetween(premiumPaidToDate, nextPaymentDate)} дней после текущей даты.
        </p>
    </c:if>
</div>

Этот полный пример включает в себя правильную обработку ошибок, проверки на null и удобное форматирование для пользователя.

Источники

  1. JSP - Handling Date - Tutorialspoint
  2. Add n days to a date - Stack Overflow
  3. Date manipulation in JSP JSTL - Small Concepts Blog
  4. Add the Number of Days in the Date in JSTL - DeveloperHelps
  5. Java Calendar add() Method - Tutorialspoint
  6. Java – Add days to Date - BeginnersBook
  7. Add 7 days to given date in jsp - Coderanch

Заключение

Добавление дней к дате в JSP можно выполнить несколькими способами, при этом класс Calendar является наиболее надежным для использования в продакшене. Для вашего конкретного случая расчета даты следующего платежа через 10 дней после текущей даты, подход с использованием Calendar обеспечивает автоматическую обработку переходов между месяцами и крайние случаи.

Ключевые выводы:

  • Используйте Calendar.add(Calendar.DAY_OF_MONTH, 10) для надежной арифметики дат
  • Всегда включайте правильную обработку ошибок и проверки на null
  • Рассмотрите возможность переноса сложной логики работы с датами в сервлеты для лучшей организации кода
  • Для современных приложений оцените возможность использования API даты и времени Java 8
  • Тестируйте ваши расчеты дат на переходах между месяцами/годами и в високосные годы

Представленные примеры дают вам несколько вариантов, от простых решений на основе скриптлетов до более сложных реализаций с использованием пользовательских функций, позволяя выбрать подход, который лучше всего соответствует требованиям и стандартам кодирования вашего приложения.

Авторы
Проверено модерацией
Модерация