即使您选择任何TimeZone,以秒为单位的时间也相同?

时间:2018-03-06 14:40:59

标签: java datetime timezone epoch

我使用以下功能在我应用TimeZone“Europe / Warsaw”后的几秒钟内获得时间。

我正确地获取日期,但是只要我在几秒钟内转换日期,我的输出就会出错。服务器在TimeZone“Europe / Warsaw”中预计秒数。什么是摆脱这种情况的最佳方式?

public static long getTimeInSeconds() {
    try {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //Here you say to java the initial timezone. This is the secret
        sdf.setTimeZone(TimeZone.getTimeZone("Europe/Warsaw"));

        //Will get in Warsaw time zone
        String date = sdf.format(calendar.getTime());

        Date date1 = sdf.parse(date);

        //Convert time in seconds as required by server.
        return (date1.getTime() / 1000);

    } catch (ParseException e) {
        e.printStackTrace();
    }

    return 0;
}

3 个答案:

答案 0 :(得分:4)

“TimeZone中的秒”没有意义,因为纪元秒表示“纪元以来的秒数”(其中< strong> epoch 1970年1月1日UTC的午夜),无论时区如何。

这个价值在世界各地都是一样的。但是,相同的纪元秒值可以转换为本地日期和时间,具体取决于时区。

示例:现在,epoch第二个值是1520352472.这个相同的值(自纪元以来的1520352472秒),在世界各地都是一样的。但是这个值可以代表每个时区的不同日期和时间:

  • 2018年3月6日,UTC时间16:07:52
  • 2018年3月6日,13:07:52在圣保罗(巴西)
  • March 7th 2018,01:07:52在东京

事情是:无论我在哪个时区,epoch秒值都是相同的,所以你根本不需要考虑任何时区。

java.util.Datedoesn't have any notion of timezone,它只包含一个long值,表示自纪元以来的毫秒数。所以,如果你有一个Date对象,只需使用这个值并除以1000:

long epochSeconds = new Date().getTime() / 1000;

实际上,如果您想要当前日期/时间的数值,您甚至无需创建Date来获取它:

long epochSeconds = System.currentTimeMillis() / 1000;

答案 1 :(得分:1)

tl; dr

要获取自1970-01-01T00:00Z的纪元参考以来的整秒计数:

Instant.now().getEpochSecond()

替代路线,结果相同:

ZonedDateTime.now( ZoneId.of( "Europe/Warsaw" ) ).toInstant().getEpochSecond()

java.time

摆脱这种情况的最佳方法是什么?

最好的方法是使用几年前取代了可怕的DateCalendarSimpleDateFormat类的现代 java.time 类。

显然您想要两件事:

  • 当前时刻,以特定地区(time zone)的人们所使用的挂钟时间显示。
  • epoch reference中1970年第一时刻UTC起的整秒计数。

第一个,获取当前时区的时刻。我们使用ZoneIdZonedDateTime类。

ZoneId z = ZoneId.of( "Europe/Warsaw" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

请参阅此code run live at IdeOne.com

zdt.toString():2020-02-09T21:14:56.417009 + 01:00 [欧洲/华沙]

要获取自1970-01-01T00:00Z以来的秒数,请提取Instant。此类表示以UTC表示的时刻,其偏移量为零小时-分钟-秒。

Instant instant = zdt.toInstant() ;

请参阅此code run live at IdeOne.com

instant.toString():2020-02-09T20:14:56.417009Z

变量zdtinstant代表时间轴上的同一时刻,同一点。只有挂钟时间不同。

询问从纪元参考开始的整秒计数。

long secondsSinceEpoch = instant.getEpochSecond() ;  // Beware of data-loss, as fractional second is ignored.

请参阅此code run live at IdeOne.com

secondsSinceEpoch:1581279296


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310

Joda-Time项目(现在位于maintenance mode中)建议迁移到java.time类。

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容打下了基础。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 2 :(得分:0)

您需要在从日历中获取时间后设置时区

public static long getTimeInSeconds() {

    try {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //Will get in Warsaw time zone
        String date = sdf.format(calendar.getTime());

        //Here you say to java the initial timezone. This is the secret
        sdf.setTimeZone(TimeZone.getTimeZone("Europe/Warsaw"));

        Date date1 = sdf.parse(date);

        //Convert time in seconds as required by server.
        return (date1.getTime() / 1000);

    } catch (ParseException e) {
        e.printStackTrace();
    }
    return 0;
}