Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.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 SimpleDateFormat显示错误的本地时间_Java_Android_Simpledateformat - Fatal编程技术网

Java SimpleDateFormat显示错误的本地时间

Java SimpleDateFormat显示错误的本地时间,java,android,simpledateformat,Java,Android,Simpledateformat,我想将一个字符串存储到Android应用程序的数据库(SQLite)中,其中包含当前时间和日期。为此,我使用SimpleDataFormat。不幸的是,它没有显示正确的时间。我尝试了两种选择 第一种选择(来自) 第二种选择(来自) 在这两种情况下,时间都是错的。这不是我的笔记本电脑或手机显示的本地时间,但输出时间提前了2小时。我怎样才能改变这一点?我想在我的电脑上显示当前的柏林时间(CEST)。非常感谢您的每一句评论。ISO 8601 假设您的SQLite没有datetime数据类型,我建议您使

我想将一个字符串存储到Android应用程序的数据库(SQLite)中,其中包含当前时间和日期。为此,我使用SimpleDataFormat。不幸的是,它没有显示正确的时间。我尝试了两种选择

第一种选择(来自)

第二种选择(来自)

在这两种情况下,时间都是错的。这不是我的笔记本电脑或手机显示的本地时间,但输出时间提前了2小时。我怎样才能改变这一点?我想在我的电脑上显示当前的柏林时间(CEST)。非常感谢您的每一句评论。

ISO 8601 假设您的SQLite没有
datetime
数据类型,我建议您使用ISO 8601格式(国际标准)将日期时间作为字符串存储到SQLite。接下来,考虑使用javaTime-现代java日期和时间API来完成日期和时间工作。这两个建议齐头并进。一般建议使用UTC存储日期和时间,但我知道您更喜欢欧洲/柏林时间

    ZoneId databaseTimeZone = ZoneId.of("Europe/Berlin");
    
    ZonedDateTime now = ZonedDateTime.now(databaseTimeZone);
    String databaseTime = now.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    
    System.out.println(databaseTime);
刚才运行时的上述输出:

2020-09-27T15:54:21.53+02:00

我故意在字符串中包含UTC的偏移量。这将允许检索字符串的任何人将时间转换为UTC或其首选时区。如果用户前往印度参观泰姬陵并在那里检索数据,转换为印度标准时间是没有问题的。当柏林从夏季时间(DST)改为标准时间并重复相同的时钟时间时,这种偏移也消除了10月份夜间时间的歧义。更改前的时间偏移量为+02:00,更改后的时间偏移量为+01:00

如何更改格式(?)

编辑:如果您坚持自己的信息格式和人类可读性,请为此构建一个格式化程序。
ZonedDateTime
已在您选择的时区中设置了时间,因此设置格式时,您也将设置该时间:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss Z");
    String databaseTime = now.format(formatter);
现在的结果是:

2020-09-27 16:22:23+0200

进一步编辑:由于人类可读性是该专栏的唯一要求,因此请全力以赴,并使用java预定义的本地化格式,例如:

    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
            .withLocale(Locale.GERMAN);
  • 2020年9月19:06:03梅斯
  • 如果太长,请使用
    FormatStyle.MEDIUM

    进一步编辑:为什么?问题是
    27。2020年9月19:06:03 MESZ比
    2020-09-27 16:22:23+0200更容易阅读和正确理解。你应该尽可能地让自己轻松。但是,包括偏移量是有意义的,
    +0200
    ,因为它是明确的,而像
    MESZ
    这样的时区缩写不能保证是明确的(许多时区缩写是模糊的)

    你的代码出了什么问题? 您可能正在时区设置为UTC(或当前比柏林时间晚两小时的其他时区)的计算机上运行代码。在第二段代码中,您试图通过将格式化程序的时区设置为CEST(中欧夏季时间)来弥补这一事实。你这样做的方式不是你想要的,而且也不起作用。两者都与CEST不是时区这一事实有关。CEST比UTC早两个小时,如果它起作用,那么在柏林仅比UTC早1小时的标准时间内,您也会比UTC早两个小时,这是错误的时间。由于CEST不是时区,
    时区
    不将其识别为时区。这和时区类一样令人困惑:它没有反对,而是默认地给你GMT,所以你什么都没有得到。我真的建议避免使用那个类。柏林的正确时区标识符是
    欧洲/柏林
    ,我在代码中也使用了该标识符。时区标识符采用地区/城市格式

    问:java.time不需要Android API级别26吗? time在较旧和较新的Android设备上都能很好地工作。它至少需要Java6

    • 在Java8和更高版本以及更新的Android设备上(API级别26),现代API是内置的
    • 在非androidjava6和7中,获取三个后端口,即现代类的后端口(三个十用于jsr310;请参见底部的链接)
    • 在较旧的Android上,可以使用desugaring或Android版本的ThreeTen Backport。它叫ThreeTenABP。在后一种情况下,请确保使用子包从
      org.threeten.bp
      导入日期和时间类
    链接
    • 解释如何使用java.time
    • ,其中首先描述了
      java.time
    • ,java.time的后端口
    到Java6和Java7(JSR-310为三十)
  • ,Android版Three Ten Backport
  • ,解释得非常透彻

  • 一周前我遇到了同样的问题,我发现问题出在时区设置上

    如果您以字符串形式获取日期,并且需要将其格式化为另一种格式,请使用下面的代码

    public String getCalendarDate(String inputDate){
            Date date = getDateFromSource(inputDate);
            SimpleDateFormat formatter = new SimpleDateFormat("EEEE, d MMMM yyyy", Locale.getDefault());
            formatter.setTimeZone(TimeZone.getDefault());
            return formatter.format(date);
        }
    
        Date getDateFromSource(String apiDate){
            Date newFormattedDate = null;
            SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
            parser.setTimeZone(TimeZone.getTimeZone("UTC"));
            try {
                 newFormattedDate = parser.parse(apiDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return newFormattedDate;
        }
    
    getDateFromSource
    函数中,将日期格式更改为源格式,而在
    getCalendarDate
    函数中,将格式更改为所需格式

    如果已经有了Date对象,可以忽略
    getDateFromSource
    函数,并将其直接放在第二个函数中

    对于使用
    Kotlin
    的用户,这是等效代码

    fun getCalendarDate(apiDate:String):String{
    val date=getDateFromApi(apiDate)
    val formatter=SimpleDataFormat(“EEEE,d MMMM yyyy”,Locale.getDefault())
    formatter.timeZone=timeZone.getDefault()
    返回格式化程序。格式(日期)
    }
    private fun getDateFromApi(apiDate:String):日期{
    val parser=SimpleDateFormat(“yyyy-MM-dd'T'HH:MM:ss'Z',Locale.ENGLISH)
    parser.ti
    
        DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                .withLocale(Locale.GERMAN);
    
    public String getCalendarDate(String inputDate){
            Date date = getDateFromSource(inputDate);
            SimpleDateFormat formatter = new SimpleDateFormat("EEEE, d MMMM yyyy", Locale.getDefault());
            formatter.setTimeZone(TimeZone.getDefault());
            return formatter.format(date);
        }
    
        Date getDateFromSource(String apiDate){
            Date newFormattedDate = null;
            SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
            parser.setTimeZone(TimeZone.getTimeZone("UTC"));
            try {
                 newFormattedDate = parser.parse(apiDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return newFormattedDate;
        }
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.TimeZone;
    
    public class Main {
        public static void main(String[] args) {
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
            sdf2.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
            System.out.println(sdf2.format(new Date()));
        }
    }
    
    2020-09-27 18:38:04 +0200
    
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    
    public class Main {
        public static void main(String[] args) {
            ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Europe/Berlin"));
    
            // Default format
            System.out.println(zdt);
    
            // Some custom format
            System.out.println(zdt.format(DateTimeFormatter.ofPattern("EEEE dd uuuu hh:mm:ss a z")));
        }
    }
    
    2020-09-27T18:42:53.620168+02:00[Europe/Berlin]
    Sunday 27 2020 06:42:53 pm CEST
    
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    
    public class Main {
        public static void main(String[] args) {
            ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("CEST"));
            // ...
        }
    }
    
    Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: CEST
        at java.base/java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:279)
        at java.base/java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:234)
        at java.base/java.time.ZoneRegion.ofId(ZoneRegion.java:120)
        at java.base/java.time.ZoneId.of(ZoneId.java:408)
        at java.base/java.time.ZoneId.of(ZoneId.java:356)
        at Main.main(Main.java:6)
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.TimeZone;
    
    public class Main {
        public static void main(String[] args) {
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
            sdf2.setTimeZone(TimeZone.getTimeZone("CEST"));
            System.out.println(sdf2.format(new Date()));
        }
    }
    
    2020-09-27 16:47:45 +0000