转换为 JSON 字符串时日期递减一天 - Java

问题描述 投票:0回答:1

我们有一个从字母数字字符串获取日期的方法。假设字符串是

Y04051000547GF
,结果日期将是
Tue May 04 00:00:00 IST 2010

public static Date getDateFromGITID(String gitId) {
    
    Date date = null;
    try {

        String dateInGit = nid.substring(1, 7); //  six characters from the second character

        DateFormat format = new SimpleDateFormat("ddMMyy", Locale.ENGLISH);
        date = format.parse(dateInGit);
    } catch (ParseException e) {
        
    }
    
    return date;
}

现在,这个日期被分配给一个类的属性

UserInfo
,当我们尝试将此类的对象转换为 JSON 时,日期会减少 1 天!

对象转JSON字符串

public static String asJsonString(final Object obj) {
    try {
        return new ObjectMapper().writeValueAsString(obj);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

用户信息Bean

public class UserInfo {
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    Date date;
}

这是主要方法

public static void main(String[] args) {
    
    UserInfo obj = new UserInfo();
    obj.date = getDateFromGITID("Y04051000547GF");
    
    System.out.println(obj.date);

    System.out.println(asJsonString(obj));
}

这是控制台输出

Tue May 04 00:00:00 IST 2010
{"dob":"2010-05-03"}

您可以看到日期是 2010 年 5 月 4 日,但在 JSON 中它会减少 1 天。我们能够找出导致问题的原因,日期以 IST 打印,与 UST 相差 5 小时 30 分钟。所以我们在 JSON 转换之前添加了该时间,转换后的时间没有变化。

public static void main(String[] args) {
    
    UserInfo obj = new UserInfo();
    obj.dob = getDOBFromNID("Y04051000547GF");
    
    System.out.println(obj.dob);

    obj.dob.setHours(5);
    obj.dob.setMinutes(30);
    obj.dob.setSeconds(00);

    System.out.println(asJsonString(obj));
}

输出

Tue May 04 00:00:00 IST 2010
{"dob":"2010-05-04"}

是的,我们使用了已弃用的方法,但它仅用于测试。即使我们尝试将时间减少 1 秒,问题也会出现。所以问题是

  1. 为什么会这样?
  2. 还有更好的解决方法吗?
java json date timezone objectmapper
1个回答
0
投票

您正在使用有严重缺陷的日期时间类,这些类在几年前已被 JSR 310 中定义的现代 java.time 类取代。

具体来说,我预计您的问题是由于使用

java.util.Date#toString
方法生成文本造成的。这个方法对你来说是骗人的。
java.util.Date
值表示日期和时间,与 UTC 时间子午线的偏移量为零时-分-秒。
toString
方法在生成文本结果时应用 JVM 当前的默认时区。

虽然本意是好的,但这种反特性给 Java 开发人员带来了无尽的困惑和痛苦。避免这门课。避免所有遗留的日期时间类!

使用行业领先的 java.time 类完成所有日期时间工作。

String original = "Y04051000547GF" ;
String input = original.substring( 1 , 7 ) ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "ddMMuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;

如果您必须与尚未更新到 java.time 的旧代码进行互操作,请使用添加到旧类中的新方法进行转换。

从一个日期到一个时刻,时间线上的一个特定点,需要一天中的某个时间,并且需要一个时区。我假设您想要该日期的第一个时刻,如 UTC 所示(偏移量为零)。

ZonedDateTime zdt = ld.atStartOfDay( ZoneOffset.UTC ) ;
Instant instant = zdt.toInstant() ;
java.util.Date d = java.util.Date.from( instant ) ;

或者,如 Ole V.V. 所评论,也许您的意思是获取特定时区中一天中的第一时刻。

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
© www.soinside.com 2019 - 2024. All rights reserved.