Java 对自定义日期格式使用GregorianCalendar

Java 对自定义日期格式使用GregorianCalendar,java,date,gregorian-calendar,Java,Date,Gregorian Calendar,我需要解析一个自定义的日期格式,该格式定义在一个我需要通信的设备中,其中的日期是从2000年算起的秒数 我尝试使用GregorianCalendar解析此数据,这是我尝试的代码: GregorianCalendar calendar = new GregorianCalendar(); calendar.setGregorianChange(new Date(2000 - 1900, 0, 1)); Date对象对应于2000年1月1日。我认为我可以通过设置timeinmill

我需要解析一个自定义的日期格式,该格式定义在一个我需要通信的设备中,其中的日期是从2000年算起的秒数

我尝试使用GregorianCalendar解析此数据,这是我尝试的代码:

    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setGregorianChange(new Date(2000 - 1900, 0, 1));
Date对象对应于2000年1月1日。我认为我可以通过设置timeinmillis来获得正确的日期乘以我读到的时间1000,因为它是以秒为单位的,而不是以毫秒为单位的GregorianCalendar,但它不起作用。我尝试了setTimeInMillis0,等待对应于日历的时间对应于2000年1月1日,但它没有,它对应于1969年12月18日

如何配置GregorianCalendar,以便将TimeInMillis0设置为对应于2000年1月1日?如果不可能,有没有其他类可以代替我自己创建所有代码


提前感谢。

创建一个2000/01/01的日期,以毫秒为单位获取时间,然后从您的设备获取以毫秒为单位的时间。添加这两个并创建日期和日历…

创建2000/01/01的日期,以毫秒为单位获取时间,然后从设备获取以毫秒为单位的时间。添加这两个元素,然后创建日期和日历…

您要做的是更改纪元,默认为2000/01/01 Unix时间戳。 因此,您想要的只是一种Unix时间戳,使用2000/01/01作为历元

我将获得unix时间戳,单位为毫秒2000/01/01,并将其保存为常量。现在,创建GregorianCalendar子类,以便您可以从输入数据中添加这些毫秒,并返回正确的日期


也许您还可以查看一下

您想要做的是更改Epoch,默认情况下是2000/01/01 Unix时间戳。 因此,您想要的只是一种Unix时间戳,使用2000/01/01作为历元

我将获得unix时间戳,单位为毫秒2000/01/01,并将其保存为常量。现在,创建GregorianCalendar子类,以便您可以从输入数据中添加这些毫秒,并返回正确的日期


也许您还可以查看一下,您正在使用不推荐的Date构造函数。而且,你用错了方法

应该是 年+1900,月,日。 据

顺便说一句,为什么不使用? 然后你会得到很多方便的东西:

DateTime dt = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour);

您正在使用已弃用的日期构造函数。而且,你用错了方法

应该是 年+1900,月,日。 据

顺便说一句,为什么不使用? 然后你会得到很多方便的东西:

DateTime dt = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour);
这样就可以了

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); // change the timezone as you wish
cal.set(Calendar.YEAR, 2000);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);   
cal.set(Calendar.HOUR, 00);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
cal.set(Calendar.MILLISECOND, 00);

cal.add(Calendar.MILLISECOND, 1000); // calculate and add your millisec here where 1000 is added 
这样就可以了

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); // change the timezone as you wish
cal.set(Calendar.YEAR, 2000);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);   
cal.set(Calendar.HOUR, 00);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
cal.set(Calendar.MILLISECOND, 00);

cal.add(Calendar.MILLISECOND, 1000); // calculate and add your millisec here where 1000 is added 
setGregorianChange仅更改从Julian切换到Gregorian的时间点。它默认为正确的历史值

但是,因为几乎所有其他人都在使用proleptic Gregorian,所以这个函数有一个有效的用例:

setGregorianChange(new Date(Long.MIN_VALUE)) //Julian never happened
这也是JodaTime默认使用的

无论如何,您可以从正常的毫秒unix时间戳中减去946684800000L,然后除以1000:

public static long secondsSince2000(Date input) {
    final long epoch = 946684800000L;
    return (input.getTime() - epoch) / 1000L;
}
要从2000年以来的秒数转换:

public static Calendar fromSecondsSince2000( long seconds ) {
    final long epoch = 946684800000L;
    Calendar cal = GregorianCalendar.getInstance();
    long timestamp = epoch + seconds * 1000L;
    cal.setTime(new Date(timestamp));
    return cal;
}
要确保两者都起作用,请执行以下操作:

    long sec = secondsSince2000(new Date());
    Calendar cal = fromSecondsSince2000( sec );
    System.out.println(cal.getTime().toString().equals(new Date().toString()));
他们应该打印true

设置GregorianChange仅更改从Julian切换到Gregorian的时间点。它默认为正确的历史值

但是,因为几乎所有其他人都在使用proleptic Gregorian,所以这个函数有一个有效的用例:

setGregorianChange(new Date(Long.MIN_VALUE)) //Julian never happened
这也是JodaTime默认使用的

无论如何,您可以从正常的毫秒unix时间戳中减去946684800000L,然后除以1000:

public static long secondsSince2000(Date input) {
    final long epoch = 946684800000L;
    return (input.getTime() - epoch) / 1000L;
}
要从2000年以来的秒数转换:

public static Calendar fromSecondsSince2000( long seconds ) {
    final long epoch = 946684800000L;
    Calendar cal = GregorianCalendar.getInstance();
    long timestamp = epoch + seconds * 1000L;
    cal.setTime(new Date(timestamp));
    return cal;
}
要确保两者都起作用,请执行以下操作:

    long sec = secondsSince2000(new Date());
    Calendar cal = fromSecondsSince2000( sec );
    System.out.println(cal.getTime().toString().equals(new Date().toString()));

他们应该打印真实的

是的,这正是我现在发现的@Thihara,我正以最艰难的方式努力。非常感谢。我会在4分钟内接受。这不包括本地时区的问题,我认为这是这件事中唯一困难的部分。本地时区?它们与正常时区不同吗?对不起,我对它们不太熟悉。我的意思是毫秒是绝对时间,当你用年/月/日字段创建一个新日期时,你在每个时区都会得到一个不同的毫秒值。对不起,如果你被冒犯了,我并不是想伤害你:是的,这正是我现在发现的@Thihara,我在用最艰难的方法。非常感谢。我会在4分钟内接受。这不包括本地时区的问题,我认为这是这件事中唯一困难的部分。本地时区?它们与正常时区不同吗?抱歉,我对它们不太熟悉。我的意思是毫秒是绝对时间,当您使用年/月/日字段创建新日期时,您在每个时区都会得到不同的毫秒值。如果冒犯了您,我很抱歉,我并不是想伤害别人:请使用此方法Calendar.getInstanceTimeZone在第一行中,很可能OP需要UTC时间
.使用此方法Calendar.getInstanceTimeZone在第一行中可能需要UTC时间。此@Esailija中唯一的一点是我希望从2000年起的秒数转换为GregorianCalendar;所以,没有必要设置时区?@HericDenis时间戳是时间上的瞬间。。。获得日历后,您可以设置时区以查看特定时刻该时区中的时间。例如,在日本,当时间点为946684800000时,几乎是2000年1月的中午,但在芬兰,是午夜2小时后。但它在时间上是相同的宇宙瞬间。明白了吗?好的@Esailija,明白了。我不知道日期格式,这真的很有用@Esailija,最后一次编辑还可以,但我尝试了calendar.getTime.toString fromssecondssince20000,结果是Fri Dec 31 22:00:00 BRST 1999,但我对calendar.getCalendar.YEAR有正确的值;calendar.getCalendar.MONTH;calendar.getCalendar.DAY(每月的第天);Akward.这个@Esailija中唯一的一件事就是我想把2000年以来的秒数转换成GregoriaCalendar;所以,没有必要设置时区?@HericDenis时间戳是时间上的瞬间。。。获得日历后,您可以设置时区以查看特定时刻该时区中的时间。例如,在日本,当时间点为946684800000时,几乎是2000年1月的中午,但在芬兰,是午夜2小时后。但它在时间上是相同的宇宙瞬间。明白了吗?好的@Esailija,明白了。我不知道日期格式,这真的很有用@Esailija,最后一次编辑还可以,但我尝试了calendar.getTime.toString fromssecondssince20000,结果是Fri Dec 31 22:00:00 BRST 1999,但我对calendar.getCalendar.YEAR有正确的值;calendar.getCalendar.MONTH;calendar.getCalendar.DAY(每月的第天);阿克沃德。