如何在Java中仅修改Date对象的时间部分,同时保留日期信息不变。

huangapple go评论103阅读模式
英文:

How to change just the time of the Date object in Java leaving the date information intact

问题

  1. public static Date adjustTimeOfDay(Date deliveryDate, String timeOfDay) {
  2. // 将交付日期的时间部分进行调整,基于给定的时间字符串 timeOfDay
  3. // 在调整时保持偏移量和时区不变
  4. return adjustedDeliveryDate; // 返回调整后的交付日期
  5. }
英文:

I have a Date variable lets say deliveryDate. It's saved in MonngoDB in this format.

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

Now I want to change the time property of delivery Date. But it has to be done based on some String which tells what time to be set. for eg String time = "7:20 AM" [ this time is based of Kuala Lumpur, Malaysia ]. Then the result should be something like :

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

Some general note : 7:20 AM Monday, in Kuala Lumpur, Federal Territory of Kuala Lumpur, Malaysia is 11:20 PM Sunday, Coordinated Universal Time (UTC).

Now given the String time and Date delivery Date. How can I obtain the results above for all cases ?

The thing that I am expecting is :

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

答案1

得分: 2

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

下面是一个用于操作的示例方法:

  1. public static Instant adjustTimeOfDay(Instant instant, String timeOfDay) {
  2. // 将 instant 转换为带有偏移的日期时间对象
  3. OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
  4. /*
  5. * 提供一个解析时间字符串的格式化器。
  6. * 请注意,这个格式化器不是非常宽松的,
  7. * 字符串必须符合 "hh:mm a" 模式。
  8. */
  9. DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
  10. .appendLiteral(':')
  11. .appendPattern("mm")
  12. .appendLiteral(' ')
  13. .appendPattern("a")
  14. .parseCaseInsensitive()
  15. .toFormatter();
  16. // 将该字符串解析为 LocalTime
  17. LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
  18. /*
  19. * 创建一个新的 OffsetDateTime,
  20. * 将新的 LocalTime 添加到旧的 UTC 日期上
  21. */
  22. OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
  23. localTime,
  24. ZoneOffset.UTC);
  25. return adjustedOdt.toInstant();
  26. }

我在类似以下的 main 方法中使用了它:

  1. public static void main(String[] args) {
  2. /*
  3. * 不是创建 Date,
  4. * 我直接在这里使用 Instant 并解析了你的示例字符串,
  5. * 所以只需使用你的 deliveryDate.toInstant()
  6. */
  7. String input = "2020-10-07T03:10:00Z";
  8. Instant instant = Instant.parse(input);
  9. // 然后取一个要设置的时间
  10. String timeOfDayUpdate = "07:20 AM";
  11. Instant adjusted = adjustTimeOfDay(instant, timeOfDayUpdate);
  12. System.out.println(input + " ==> " + OffsetDateTime.ofInstant(adjusted, ZoneOffset.UTC)
  13. .format(DateTimeFormatter.ISO_INSTANT));
  14. }

它产生了以下输出:

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

EDIT

你可以将该方法重写为:

  1. public static Date adjustTimeOfDay(Date date, String timeOfDay) {
  2. // 将日期转换为 instant,然后将 instant 转换为带有偏移的日期时间对象
  3. OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
  4. // 提供一个解析时间字符串的格式化器
  5. DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
  6. .appendLiteral(':')
  7. .appendPattern("mm")
  8. .appendLiteral(' ')
  9. .appendPattern("a")
  10. .parseCaseInsensitive()
  11. .toFormatter();
  12. // 将该字符串解析为 LocalTime
  13. LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
  14. /*
  15. * 创建一个新的 OffsetDateTime,
  16. * 将新的 LocalTime 添加到旧的 UTC 日期上
  17. */
  18. OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
  19. localTime,
  20. ZoneOffset.UTC);
  21. // 从 OffsetDateTime 获取的 Instant 返回一个 Date
  22. return Date.from(adjustedOdt.toInstant());
  23. }

传入一个 Date,并返回一个日期。

英文:

You can use the compatibility method java.util.Date.toInstant(), manipulate the time of day of that Instant which creates a different Instant and then convert back to a Date by Date.from(Instant instant).

Here's an example method for the manipulation:

  1. public static Instant adjustTimeOfDay(Instant instant, String timeOfDay) {
  2. // convert the instant to an offset-aware datetime object
  3. OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
  4. /*
  5. * provide a formatter that parses a time-of-day String.
  6. * PLEASE NOT that this formatter is not very lenient,
  7. * the String must be of the pattern "hh:mm a"
  8. */
  9. DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
  10. .appendLiteral(':')
  11. .appendPattern("mm")
  12. .appendLiteral(' ')
  13. .appendPattern("a")
  14. .parseCaseInsensitive()
  15. .toFormatter();
  16. // parse that String to a LocalTime
  17. LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
  18. /*
  19. * create a new OffsetDateTime
  20. * adding the new LocalTime to the old LocalDate at UTC
  21. */
  22. OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
  23. localTime,
  24. ZoneOffset.UTC);
  25. return adjustedOdt.toInstant();
  26. }

I used in a main like this:

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

which created the following output:

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

EDIT

You can rewrite that method to

  1. public static Date adjustTimeOfDay(Date date, String timeOfDay) {
  2. // convert the date to an instant and the instant to an offset-aware datetime object
  3. OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
  4. // provide a formatter that parses a time-of-day String
  5. DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
  6. .appendLiteral(':')
  7. .appendPattern("mm")
  8. .appendLiteral(' ')
  9. .appendPattern("a")
  10. .parseCaseInsensitive()
  11. .toFormatter();
  12. // parse that String to a LocalTime
  13. LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
  14. /*
  15. * create a new OffsetDateTime
  16. * adding the new LocalTime to the old LocalDate at UTC
  17. */
  18. OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
  19. localTime,
  20. ZoneOffset.UTC);
  21. // return a Date from the Instant you get out of the OffsetDateTime
  22. return Date.from(adjustedOdt.toInstant());
  23. }

passing a Date and getting one returned.

答案2

得分: 2

  1. 如果我正确理解您的要求您正在寻找类似以下的内容
  2. import java.time.LocalTime;
  3. import java.time.ZoneId;
  4. import java.time.ZoneOffset;
  5. import java.time.ZonedDateTime;
  6. import java.time.format.DateTimeFormatter;
  7. import java.time.format.DateTimeFormatterBuilder;
  8. import java.util.Locale;
  9. public class Main {
  10. public static void main(String[] args) {
  11. // 测试
  12. System.out.println(adjustTimeOfDay("2020-10-07T03:10:00Z", "7:20 AM"));
  13. }
  14. public static String adjustTimeOfDay(String deliveryDate, String timeOfDay) {
  15. // 定义解析时间为 7:20 AM 的格式化器
  16. DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder()
  17. .parseCaseInsensitive()
  18. .appendPattern("h:m a")
  19. .toFormatter(Locale.ENGLISH);
  20. return ZonedDateTime.parse(deliveryDate)
  21. .toLocalDate()
  22. .atTime(LocalTime.parse(timeOfDay, timeFormatter))
  23. .atZone(ZoneId.of("Asia/Kuala_Lumpur"))
  24. .withZoneSameInstant(ZoneOffset.UTC)
  25. .format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss")) + 'Z';
  26. }
  27. }
  28. **输出:**
  29. 2020-10-06T23:20:00Z
  30. 我建议您在24小时制中使用`HH`然而如果您想要忽略`AM/PM`并获得时间字符串您可以在上述模式中使用`hh`然后您将获得`2020-10-06T11:20:00Z`但我不建议这样做因为这会令人困惑)。
英文:

If I understood your requirement correctly, you are looking for something like:

  1. import java.time.LocalTime;
  2. import java.time.ZoneId;
  3. import java.time.ZoneOffset;
  4. import java.time.ZonedDateTime;
  5. import java.time.format.DateTimeFormatter;
  6. import java.time.format.DateTimeFormatterBuilder;
  7. import java.util.Locale;
  8. public class Main {
  9. public static void main(String[] args) {
  10. // Test
  11. System.out.println(adjustTimeOfDay("2020-10-07T03:10:00Z", "7:20 AM"));
  12. }
  13. public static String adjustTimeOfDay(String deliveryDate, String timeOfDay) {
  14. // Define the formatter to parse time like 7:20 AM
  15. DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder()
  16. .parseCaseInsensitive()
  17. .appendPattern("h:m a")
  18. .toFormatter(Locale.ENGLISH);
  19. return ZonedDateTime.parse(deliveryDate)
  20. .toLocalDate()
  21. .atTime(LocalTime.parse(timeOfDay, timeFormatter))
  22. .atZone(ZoneId.of("Asia/Kuala_Lumpur"))
  23. .withZoneSameInstant(ZoneOffset.UTC)
  24. .format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss")) + 'Z';
  25. }
  26. }

Output:

  1. 2020-10-06T23:20:00Z

I recommend you use use HH for a time in 24-hour format. However, if you want to get a time string by ignoring AM/PM, you can use hh in the pattern given above and then you will get 2020-10-06T11:20:00Z (but I do not recommend it as it will be confusing for anyone).

huangapple
  • 本文由 发表于 2020年10月5日 14:09:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/64203235.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定