Jackson LocalDate:序列化期间放假一天

时间:2018-12-11 00:18:51

标签: 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脚本自动生成或在日期范围内指定的,因此,票证具有每周的星期一和星期日:

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 useJDBCCompliantTimezoneShift=false&useLegacyDatetimeCode=false&serverTimezone=UTC中指定了spring.datasource.url

1 个答案:

答案 0 :(得分:0)

时区问题

尽可能多 事实证明,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);
    }
}