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

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

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

问题

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

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

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 :

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 :

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
}

答案1

得分: 2

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

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

public static Instant adjustTimeOfDay(Instant instant, String timeOfDay) {
    // 将 instant 转换为带有偏移的日期时间对象
    OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
    
    /*
     * 提供一个解析时间字符串的格式化器。
     * 请注意,这个格式化器不是非常宽松的,
     * 字符串必须符合 "hh:mm a" 模式。
     */
    DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
            .appendLiteral(':')
            .appendPattern("mm")
            .appendLiteral(' ')
            .appendPattern("a")
            .parseCaseInsensitive()
            .toFormatter();
    
    // 将该字符串解析为 LocalTime
    LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
    
    /*
     * 创建一个新的 OffsetDateTime,
     * 将新的 LocalTime 添加到旧的 UTC 日期上
     */
    OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
            localTime,
            ZoneOffset.UTC);
    
    return adjustedOdt.toInstant();
}

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

public static void main(String[] args) {
    /*
     * 不是创建 Date,
     * 我直接在这里使用 Instant 并解析了你的示例字符串,
     * 所以只需使用你的 deliveryDate.toInstant()
     */
    String input = "2020-10-07T03:10:00Z";
    Instant instant = Instant.parse(input);
    // 然后取一个要设置的时间
    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

EDIT

你可以将该方法重写为:

public static Date adjustTimeOfDay(Date date, String timeOfDay) {
    // 将日期转换为 instant,然后将 instant 转换为带有偏移的日期时间对象
    OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
    
    // 提供一个解析时间字符串的格式化器
    DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
            .appendLiteral(':')
            .appendPattern("mm")
            .appendLiteral(' ')
            .appendPattern("a")
            .parseCaseInsensitive()
            .toFormatter();
    
    // 将该字符串解析为 LocalTime
    LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
    
    /*
     * 创建一个新的 OffsetDateTime,
     * 将新的 LocalTime 添加到旧的 UTC 日期上
     */
    OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
            localTime,
            ZoneOffset.UTC);
    // 从 OffsetDateTime 获取的 Instant 返回一个 Date
    return Date.from(adjustedOdt.toInstant());
}

传入一个 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:

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();
}

I used in a main like this:

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));
}

which created the following output:

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

EDIT

You can rewrite that method to

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());
}

passing a Date and getting one returned.

答案2

得分: 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) {
    		// 测试
    		System.out.println(adjustTimeOfDay("2020-10-07T03:10:00Z", "7:20 AM"));
    	}
    
    	public static String adjustTimeOfDay(String deliveryDate, String timeOfDay) {
    		// 定义解析时间为 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

我建议您在24小时制中使用`HH`。然而如果您想要忽略`AM/PM`并获得时间字符串您可以在上述模式中使用`hh`,然后您将获得`2020-10-06T11:20:00Z`(但我不建议这样做因为这会令人困惑)。
英文:

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

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';
}
}

Output:

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:

确定