【问题标题】:How to change just the time of the Date object in Java leaving the date information intact如何在 Java 中仅更改 Date 对象的时间而保持日期信息不变
【发布时间】:2020-10-05 17:43:22
【问题描述】:

我有一个日期变量,可以说是交付日期。它以这种格式保存在 MonngoDB 中。

ISODate("2020-10-07T03:10:00Z")

现在我想更改交货日期的时间属性。但它必须基于一些告诉设置时间的字符串来完成。例如 String time = "7:20 AM" [此时间以马来西亚吉隆坡为基地]。那么结果应该是这样的:

deliveryDate = ISODate("2020-10-07T11:20:00Z")

一般注意事项:马来西亚吉隆坡联邦直辖区吉隆坡星期一上午 7:20 是协调世界时 (UTC) 星期日晚上 11:20。

现在给出字符串时间和日期交付日期。我怎样才能获得所有情况下的上述结果?

我期待的是:

public static Date adjustTimeOfDay(Date deliveryDate, String timeOfDay) {
    // Adjust the time of the day of deliveryDate on the basis of timeOfDay 
    // Keep the offset and zone same while adjusting
    return deliveryDate
}

【问题讨论】:

  • deliveryDatejava.util.Date 吗? Instant 是一个不错的选择,如果您有 String,还有其他选择。
  • 是的,它是一个 java.util.Date @deHaar
  • 我根本不会用那个,你能换成LocalDateTimeOffsetDateTime吗?之后很容易操纵一天中的时间或区域。
  • 你能帮我怎么做吗@deHaar
  • 我不希望它从 MongoDB 映射到 java。我正在努力更改代码库。所以在对象中有这个属性deliveryDate,它是java.util.Date。现在我需要创建一个接收 this.time 和 this.deliverydate 的方法并返回更改后的 this.deliveryDate。

标签: java date datetime date-conversion


【解决方案1】:

您可以使用兼容性方法java.util.Date.toInstant(),操作该Instant 的时间,从而创建一个不同的Instant,然后通过Date.from(Instant instant) 转换回Date

这是一个操作的示例方法:

public static Instant adjustTimeOfDay(Instant instant, String timeOfDay) {
    // convert the instant to an offset-aware datetime object
    OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
    
    /*
     * provide a formatter that parses a time-of-day String.
     * PLEASE NOT that this formatter is not very lenient,
     * the String must be of the pattern "hh:mm a"
     */
    DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
            .appendLiteral(':')
            .appendPattern("mm")
            .appendLiteral(' ')
            .appendPattern("a")
            .parseCaseInsensitive()
            .toFormatter();
    
    // parse that String to a LocalTime
    LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
    
    /*
     * create a new OffsetDateTime
     * adding the new LocalTime to the old LocalDate at UTC
     */
    OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
                                                                localTime,
                                                                ZoneOffset.UTC);
    
    return adjustedOdt.toInstant();
}

我在main 中使用过这样的:

public static void main(String[] args) {
    /*
     * instead of creating a Date,
     * I directly use Instant here and parse your example String,
     * so just use your deliveryDate.toInstant()
     */
    String input = "2020-10-07T03:10:00Z";
    Instant instant = Instant.parse(input);
    // then take a time of day to be set
    String timeOfDayUpdate = "07:20 AM";
    Instant adjusted = adjustTimeOfDay(instant, timeOfDayUpdate);
    System.out.println(input + " ==> " + OffsetDateTime.ofInstant(adjusted, ZoneOffset.UTC)
                                                        .format(DateTimeFormatter.ISO_INSTANT));
}

创建了以下输出:

2020-10-07T03:10:00Z ==> 2020-10-07T07:20:00Z

编辑

您可以将该方法重写为

public static Date adjustTimeOfDay(Date date, String timeOfDay) {
    // convert the date to an instant and the instant to an offset-aware datetime object
    OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
    
    // provide a formatter that parses a time-of-day String 
    DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
            .appendLiteral(':')
            .appendPattern("mm")
            .appendLiteral(' ')
            .appendPattern("a")
            .parseCaseInsensitive()
            .toFormatter();
    
    // parse that String to a LocalTime
    LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
    
    /*
     * create a new OffsetDateTime
     * adding the new LocalTime to the old LocalDate at UTC
     */
    OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
            localTime,
            ZoneOffset.UTC);
    // return a Date from the Instant you get out of the OffsetDateTime
    return Date.from(adjustedOdt.toInstant());
}

传递Date 并返回一个。

【讨论】:

  • 感谢您的回答。你几乎是我需要的,但唯一的区别是我将发送一个 java.util.Date 而不是 Instant 并且我需要返回的 java.util.Date。我稍微编辑了我的问题以添加我所期望的虚拟方法。你能看一下吗@deHaar。将 deliveryDate.toInstant() 发送到 adjustTimeOfDay 并通过 new Date(Instant) 转换返回的 Instant 是否有效?我的结果?
  • 好吧,我在答案文本中描述了这一点(未完全在代码 cmets 中)@VishalAnand。你基本上拿你的Date,用deliveryDate.toInstant()把它变成Instant,用我的方法并用Date.from(instant)格式化它,不是new Date(instant)
【解决方案2】:

如果我正确理解了您的要求,您正在寻找类似的东西:

import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(adjustTimeOfDay("2020-10-07T03:10:00Z", "7:20 AM"));
    }

    public static String adjustTimeOfDay(String deliveryDate, String timeOfDay) {
        // Define the formatter to parse time like 7:20 AM
        DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder()
                                            .parseCaseInsensitive()
                                            .appendPattern("h:m a")
                                            .toFormatter(Locale.ENGLISH);

        return ZonedDateTime.parse(deliveryDate)
                .toLocalDate()
                .atTime(LocalTime.parse(timeOfDay, timeFormatter))
                .atZone(ZoneId.of("Asia/Kuala_Lumpur"))
                .withZoneSameInstant(ZoneOffset.UTC)
                .format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss")) + 'Z';

    }
}

输出:

2020-10-06T23:20:00Z

我建议您使用 HH 以 24 小时格式显示时间。但是,如果您想通过忽略AM/PM 来获取时间字符串,则可以在上面给出的模式中使用hh,然后您将得到2020-10-06T11:20:00Z(但我不推荐它,因为它会让任何人感到困惑) .

【讨论】:

  • 这是我想回答的,但 OP 坚持使用java.util.Date,所以使用旧的兼容性方法是我认为最接近最佳答案的方法。问题中给出的示例具有误导性,因为 OP 有一个 Date 并希望调整其时间。一般来说,这是一个更好的答案;-)
  • @deHaar - 有时你的无私让我觉得❤️你有多大!
  • 这一切都是为了未来的读者 ;-) 他们应该能够看到 OP 想要的解决方案和(更好的)替代方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多