Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从没有时区的字符串到欧洲/柏林的时间_Java_Timezone_Jodatime - Fatal编程技术网

Java 从没有时区的字符串到欧洲/柏林的时间

Java 从没有时区的字符串到欧洲/柏林的时间,java,timezone,jodatime,Java,Timezone,Jodatime,我花了整整一天的时间来解析一个日期,我从一个系统中得到了一个没有时区的字符串,变成了一个有时区和应用时差的字符串 原始字符串:“01/27/2021 14:47:29” 目标字符串:“2021-01-27T13:47:29.000+01:00” 问题:目标系统无法更改格式。 我需要应用,它会自动减去正确的小时数,这取决于夏季/冬季时间。所以这不是一个只减去-1的解决方案 我试过几个 这是我最后一次尝试,几乎是正确的,但它无法正确更改时间: DateTimeFormatter fmt = Date

我花了整整一天的时间来解析一个日期,我从一个系统中得到了一个没有时区的字符串,变成了一个有时区和应用时差的字符串

原始字符串:“01/27/2021 14:47:29”

目标字符串:“2021-01-27T13:47:29.000+01:00”

问题:目标系统无法更改格式。 我需要应用,它会自动减去正确的小时数,这取决于夏季/冬季时间。所以这不是一个只减去-1的解决方案

我试过几个 这是我最后一次尝试,几乎是正确的,但它无法正确更改时间:

DateTimeFormatter fmt = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss").withZone(DateTimeZone.forID(
                "Europe/Berlin"));
DateTime dt = fmt.parseDateTime(lastModifid);
dt.toString()
结果是“2021-01-27T14:47:29.000+01:00”

应用这些时差难道没有一个简单的解决方案吗?

答案(因为Java 8)是使用。我不认为你需要做任何“时区算术”来做你需要的事情。只需将时间从一个区域转换为另一个区域,如下所示:

    ZoneId sourceTZ = ZoneId.of(...);    //String denoting source time zone
    ZoneId targetTZ = ZoneId.of(...);  //String denoting target time zone
     
    LocalDateTime now = LocalDateTime.now();
     
    ZonedDateTime sourceTime = now.atZone(sourceTZ);       
    ZonedDateTime targetTime = sourceTime.withZoneSameInstant(targetTZ);
    String originalString = "01/27/2021 14:47:29";
    
    OffsetDateTime dateTime = LocalDateTime.parse(originalString, formatter)
            .atOffset(ZoneOffset.UTC);
    String targetString = dateTime.atZoneSameInstant(targetZone)
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    
    System.out.println(targetString);
在此之后,您可以使用
DateTimeFormatter
根据需要格式化时间戳字符串。

java.time 我只是把hfontanez的好建议说得再详细一点。我首先宣布:

private static final DateTimeFormatter formatter
        = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss");
private static final ZoneId targetZone = ZoneId.of("Europe/Berlin");
然后处理字符串的过程如下所示:

    ZoneId sourceTZ = ZoneId.of(...);    //String denoting source time zone
    ZoneId targetTZ = ZoneId.of(...);  //String denoting target time zone
     
    LocalDateTime now = LocalDateTime.now();
     
    ZonedDateTime sourceTime = now.atZone(sourceTZ);       
    ZonedDateTime targetTime = sourceTime.withZoneSameInstant(targetTZ);
    String originalString = "01/27/2021 14:47:29";
    
    OffsetDateTime dateTime = LocalDateTime.parse(originalString, formatter)
            .atOffset(ZoneOffset.UTC);
    String targetString = dateTime.atZoneSameInstant(targetZone)
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    
    System.out.println(targetString);
输出为:

2021-01-27T15:47:29+01:00

你要求13:47:29.000,我给你15:47:29。为什么?

  • 我假设原始字符串是UTC格式的,所以在代码中我明确告诉Java以这种方式解释它。如果这个假设是正确的,那么你似乎误解了。德国时间(欧洲/柏林)、标准+01:00和夏季时间(DST)期间+02:00的偏移量意味着德国比UTC提前1或2小时,因此我们需要加上,而不是减去1或2小时。正如hfontanez已经说过的,图书馆正在为我们做正确的事情
  • 您要求的格式以及Joda Time生成的格式也是ISO 8601。根据ISO 8601,秒的小数在为零时是可选的,因此出于您的目的,您不需要目标字符串的
    .000
    部分
和hfontanez一样,我也在使用java.time,这是现代java日期和时间API。为什么?我认为Java.时间是JoDaTime的好继任者。Joda Time主页上自己写着(黑体字是原创):

注意,从JavaSE8开始,用户被要求迁移到
Java.time
(JSR-310)——JDK的核心部分,它取代了这一功能 项目。

你的代码出了什么问题? 您正在将
.withZone(DateTimeZone.forID(“Europe/Berlin”))
应用于用于解析原始字符串的格式化程序。这与告诉Joda Time原始字符串已经是德国时间相同。因此,从那一刻起,Joda Time决定不需要对时间进行转换,只需返回一天中相同的时间。相反,我们首先需要指定原始字符串所在的时区,然后将其转换为德国时间

链接
  • 解释如何使用java.time
使用Java SE 8日期和时间API 下面的代码

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss", Locale.ENGLISH)
                                    .withZone(ZoneId.of("Africa/Johannesburg"));
ZonedDateTime zdtSource = ZonedDateTime.parse(strSource, fmt);
做的事情和

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss", Locale.ENGLISH);
ZonedDateTime zdtSource = LocalDateTime.parse(strSource, fmt)
                                    .atZone(ZoneId.of("Africa/Johannesburg"));
这意味着使用解析器应用时区是一种要求解析器将日期时间字符串解析为本地日期时间并将时区固定在其上的方法

现在您已经理解了这个概念,让我们讨论一下您发布的需求

从一个没有时区的字符串到一个有 时区和应用时差

原始字符串:“01/27/2021 14:47:29”

目标字符串:“2021-01-27T13:47:29.000+01:00”

问题:目标系统无法更改格式。我需要申请, 它会自动减去正确的小时数, 取决于夏季/冬季时间。所以这并不是一个解决方案 减去-1

这里有两件事需要理解:

  • 只有当给定的本地日期时间来自时区偏移量为
    UTC+02:00
    的时区时,才能将给定的本地日期时间转换为目标日期时间,例如
    非洲/约翰内斯堡
    。描述了
    欧洲/柏林的时区
  • ZonedDateTime
    设计用于根据夏季/冬季时间自动调整日期时间;因此,您不需要明确地执行任何操作
  • 说够了;让我们看一些代码

    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String strSource = "01/27/2021 14:47:29";
            DateTimeFormatter fmtInput = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss", Locale.ENGLISH);
            ZonedDateTime zdtSource = LocalDateTime.parse(strSource, fmtInput)
                                            .atZone(ZoneId.of("Africa/Johannesburg"));
            System.out.println(zdtSource);
    
            ZonedDateTime zdtTarget = zdtSource.withZoneSameInstant(ZoneId.of("Europe/Berlin"));
            // Default format
            System.out.println(zdtTarget);
            // Custom format
            DateTimeFormatter fmtOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
            System.out.println(zdtTarget.format(fmtOutput));
        }
    }
    
    输出:

    2021-01-27T14:47:29+02:00[Africa/Johannesburg]
    2021-01-27T13:47:29+01:00[Europe/Berlin]
    2021-01-27T13:47:29.000+01:00
    
    2021-01-27T14:47:29.000+02:00
    2021-01-27T13:47:29.000+01:00
    
    了解有关的更多信息

    使用Joda时间API 注意:请在

    Joda Time是Java事实上的标准日期和时间库 在JavaSE8之前。现在要求用户迁移到java.time (JSR-310)

    但是,为了完整起见,我使用Joda time API编写了以下代码:

    import org.joda.time.DateTime;
    import org.joda.time.DateTimeZone;
    import org.joda.time.format.DateTimeFormat;
    import org.joda.time.format.DateTimeFormatter;
    
    public class Main {
        public static void main(String[] args) {
            String strSource = "01/27/2021 14:47:29";
            DateTimeFormatter fmtInput = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss")
                                            .withZone(DateTimeZone.forID("Africa/Johannesburg"));
    
            DateTime dtSource = fmtInput.parseDateTime(strSource);
            System.out.println(dtSource);
    
            DateTime dtTarget = dtSource.withZone(DateTimeZone.forID("Europe/Berlin"));
            System.out.println(dtTarget);
        }
    }
    
    输出:

    2021-01-27T14:47:29+02:00[Africa/Johannesburg]
    2021-01-27T13:47:29+01:00[Europe/Berlin]
    2021-01-27T13:47:29.000+01:00
    
    2021-01-27T14:47:29.000+02:00
    2021-01-27T13:47:29.000+01:00
    

    回答得很好,但是您应该合并解析作为问题一部分的输入字符串,并删除
    。现在调用
    。(1)原始字符串是否使用UTC?在这种情况下,你必须为柏林增加1或2个小时,而不是减少。(2) 你需要利用乔达的时间吗?今天大多数人(包括Joda Time本身)建议你使用。我无法更好地解释它。谢谢你的解释。有时有些概念我能理解,但无法雄辩地解释。你抓住了我想解释的一切。基本上,让图书馆做它的工作,简化你的生活!基本上,让图书馆做它的工作,简化你的生活!我称之为雄辩!谢谢你的评论。非常感谢你的解释。这就像一个符咒,我甚至理解它,谢谢。