【问题标题】:How to convert GregorianCalendar to Python / Jython datetime?如何将 GregorianCalendar 转换为 Python / Jython 日期时间?
【发布时间】:2020-09-22 07:46:09
【问题描述】:

我正在使用 Jython 进行编程,我想将 java.util.GregorianCalendar 日期时间实例转换为 Jython 日期时间值。

我试过这个:

from java.util import Calendar, GregorianCalendar
import datetime

x = GregorianCalendar.getInstance()

y = datetime(x.YEAR, x.MONTH, x.DAY_OF_MONTH, x.HOUR_OF_DAY, x.MINUTE, x.SECOND, x.MILLISECOND)

但我收到以下错误:

TypeError: 'module' object is not callable

然后我运行了这个程序,我惊讶地发现日志中写入了错误的值。例如,假设年份为 2020 年,但在日志中显示为“1”。

from java.util import Calendar, GregorianCalendar
import datetime


x = GregorianCalendar.getInstance()

print x
print "Year", x.YEAR
print "Month",x.MONTH
print "Day", x.DAY_OF_MONTH
print "Hour", x.HOUR_OF_DAY
print "Minute", x.MINUTE
print "Second", x.SECOND
print "Millisecond", x.MILLISECOND
print x.getTime()

日志:

java.util.GregorianCalendar[time=1591195394508,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2020,MONTH=5,WEEK_OF_YEAR=23,WEEK_OF_MONTH=1,DAY_OF_MONTH=3,DAY_OF_YEAR=155,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=4,HOUR_OF_DAY=16,MINUTE=43,SECOND=14,MILLISECOND=508,ZONE_OFFSET=3600000,DST_OFFSET=3600000]
Year 1
Month 2
Day 5
Hour 11
Minute 12
Second 13
Millisecond 14
Wed Jun 03 16:43:14 CEST 2020

谁能告诉我我做错了什么?

【问题讨论】:

标签: java python date jython gregorian-calendar


【解决方案1】:

java.time.ZonedDateTime 替换 GregorianCalendar

仅供参考,您正在使用可怕的日期时间类 (GregorianCalendar),这些类现在已成为遗留问题,多年前已被 JSR 310 中定义的现代 java.time 类所取代。

使用添加到旧类的新方法进行转换。 ZonedDateTime 替换 GregorianCalendar

ZonedDateTime zdt = myGregCal.toZonedDateTime() ;

继续提取零件。

不需要在月份中添加一个,因为 java.time 使用正常的月份编号,1-12 表示 1 月至 12 月。仅使用 java.time 而非 GregorianCalendar 的众多原因之一。

在 Java 语法中(我不知道 Jython):

int year = zdt.getYear() ; 
int month = zdt.getMonthValue() ;
int day = zdt.getDayOfMonth() ;
int hour = zdt.getHour() ;
int minute = zdt.getMinute() ;
int second = zdt.getSecond() ;
long micro = TimeUnit.NANOSECONDS.toMicros( zdt.getNano() ) ;  // Convert from the nanosecond resolution of java.time to the microsecond resolution of Jython datetime.
String timeZoneId = zdt.getZone().getId() ;

问题中看到的代码中有两个问题:

  • 您使用毫秒,但datetime 的构造函数需要微秒。在这里,我们将 java.time 中使用的纳秒转换为 Jython datetime 中使用的微秒。
  • 您忽略了将时区传递给datetime 的构造函数。这里我们提取时区的ID,一个Continent/Region格式的字符串,比如Europe/Paris或者Pacific/Auckland

仅供参考,旧的 DateGregorianCalendar 类的分辨率为毫秒。 Jython datetime 类型解析为微秒。 java.time 类型使用纳秒的分辨率。



关于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 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 和 JPA 2.2 支持 java.time

从哪里获得 java.time 类?

【讨论】:

    【解决方案2】:

    这样就可以了:

    from java.util import Calendar, GregorianCalendar
    import datetime
    
    
    x = GregorianCalendar.getInstance()
    
    print x
    print "Year", x.get(Calendar.YEAR)
    print "Month",x.get(Calendar.MONTH)
    print "Day", x.get(Calendar.DAY_OF_MONTH)
    print "Hour", x.get(Calendar.HOUR_OF_DAY)
    print "Minute", x.get(Calendar.MINUTE)
    print "Second", x.get(Calendar.SECOND)
    print "Millisecond", x.get(Calendar.MILLISECOND)
    
    y = datetime.datetime(x.get(Calendar.YEAR), x.get(Calendar.MONTH)+1,x.get(Calendar.DAY_OF_MONTH), x.get(Calendar.HOUR_OF_DAY), x.get(Calendar.MINUTE), x.get(Calendar.SECOND), x.get(Calendar.MILLISECOND)*1000)
    
    print y
    print x.getTime()
    

    【讨论】:

    • 不正确。您没有将时区从 GregorianCalendar 传递给 Jython datetime 的构造函数。
    • @BasilBourque 你是对的。我编辑了我的回复。毫秒现在乘以 1000。我仍然需要弄清楚如何将时区信息从 GregorianCalendar 传输到 Jython 日期时间。我明天可能会调查一下。目前,我对结果感到满意。
    • 你不应该对此感到满意。 GregorianCalendar 太可怕了。 Sun、Oracle 和 JCP 社区几年前就放弃了该课程,采用了JSR 310,您也应该如此。考虑使用 java.time,如我的答案所示。
    • 我意识到了这一点,但我不能使用 java.time,因为我正在开发两个系统之间的接口。系统 A 将日期信息作为 GregorianCalendar 发送,系统 B 期望此日期信息作为 python 日期时间。我无权访问任何一个系统。
    • 易于转换为GregorianCalendarZonedDateTimeGregorianCalendar.from( ZonedDateTime )GregorianCalendar::toZonedDateTime
    猜你喜欢
    • 2023-03-30
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 2010-11-03
    相关资源
    最近更新 更多