java - jackson 本地日期 : one day off during serialization

标签 java spring date spring-boot jackson

当 Jackson 尝试序列化我的类中的 LocalDate 列时,我遇到了问题,但数据库完全正常,每次 JSON 显示与数据库无关的一天。

当数据库按预期显示时:

2018-10-01

调用 Spring REST 入口点的 JSON 输出:

{ "ticketStart": "2018-09-30"}

这表明已经浪费了一天的时间。数据库表不存储时间,只存储预期的日期,时区完全可以丢弃,因为我的项目是供内部使用的。我尝试用谷歌搜索我的具体问题,唯一找到的thisthis ,但他们都没有解决我的问题。

有一种方法可以强制按原样序列化数据库中的日期(也称为:禁用转换)。

实体代码:

@Entity
@Table(name="tickets")
public class Ticket
{
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Getter
  @Setter
  private long TicketId;

  @Column(unique=true)
  @Getter
  @Setter
  private LocalDate TicketStart;

  @Column(unique=true)
  @Getter
  @Setter
  private LocalDate TicketEnd;

  //.... some fields omitted
}

由于 Tickets 实体是由 CRON 脚本自动生成或在日期范围内指定的,其中 Ticket 具有每周的星期一和星期日:

public Ticket GenerateEmptyTicket(LocalDate begin, LocalDate end)
{
    Ticket newTicket = new Ticket();

    newTicket.setTicketStart(begin);
    newTicket.setTicketEnd(end);
    newTicket.setYear(begin.getYear());
    newTicket.setMonth(begin.getMonth());
    newTicket.setLastMod(new Date());

    boolean isLocked = false;
    LocalDate date = LocalDate.now();
    if(date.isAfter(end)) isLocked = true;

    newTicket.setLocked(isLocked);

    //@TODO: Set a default responsible in the configuration.
    SystemUser rootUser = usersRepo.findByUsername("root").get();
    newTicket.setResponsable(rootUser);

    return newTicket;
}

public void GenerateTicketsBetweenTwoDates(LocalDate begin, LocalDate end)
{        
    List<LocalDate> weekDates = new ArrayList<>();

    if(begin.getDayOfWeek() != DayOfWeek.MONDAY)
        while(begin.getDayOfWeek()  != DayOfWeek.MONDAY)
            begin = begin.minusDays(1);


    LocalDate tmp = begin;
    while(tmp.isBefore(end)){
        weekDates.add(tmp);
        tmp = tmp.plusWeeks(1);
    }

    if(end.getDayOfWeek() == DayOfWeek.MONDAY)
        weekDates.add(end);


    LocalDate current = LocalDate.now();
    List<Ticket> ticketsToSave = new ArrayList<>();

    for(LocalDate dat : weekDates)
    {
        logger.info("BEGIN DATE:" + dat.toString());
        LocalDate __end = dat.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        if(current.isAfter(__end)) logger.info("LOCKED: YES");

        ticketsToSave.add(GenerateEmptyTicket(dat, __end));
    }

    ticketsRepo.saveAll(ticketsToSave);
}    

数据库和 Jackson 序列化没有显示任何错误,只是序列化产生了不希望的“休息日”结果。

注意:数据库 JDBC 连接 (MySQL) 从 application.properties spring.datasource.url 指定 useJDBCCompliantTimezoneShift=false&useLegacyDatetimeCode=false&serverTimezone=UTC

最佳答案

时区问题

一样多 事实证明,Spring 从数据库中检索日期,我猜它使用 java.util.Date (考虑系统时区)首先解析它,然后将其转换为 java.time.LocalDate ,使用TimeZone.setDefault(TimeZone.getTimeZone("UTC"));完全解决问题,像这样使用它:

@SpringBootApplication
public class MyTicketApplication {

    public static void main(String[] args) {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
        SpringApplication.run(MyTicketApplication.class, args);
    }
}

关于java - jackson 本地日期 : one day off during serialization,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53715653/

相关文章:

PHP MySQL查询按1个月之前的日期显示表的当前日期

PHPExcel:如何设置单元格的日期格式

java - IntelliJ 格式化组声明就像在 Eclipse 中一样,但跨空行

java - 使用 new() 实例化的对象中的 Spring Autowired 对象

eclipse - 导入不同项目的resources=applicationContext.xml时eclipse中的Tomcat抛出FileNotFoundException

php - 也许使用 JOIN 选择 65 年内的日期范围?

java - 如何在从数据库获取数据的同时创建异步任务加载后台

java - GSON 的奇怪行为

java - 无法使用最新的 Firebase 版本创建用户。我得到一个 W/DynamiteModule 和 W/GooglePlayServicesUtil

java - Spring Boot JPA 保留具有空列的父级的子级