【发布时间】:2016-03-30 19:41:02
【问题描述】:
我在一个应用程序 API (DFC) 下工作,它给了我一个类似日期的对象 (IDfTime)。 API 自动将日期转换为本地时区 (EST)。我需要转换为 UTC 以发送到 oracle 数据库。出于某种原因,我的代码增加了一个月。我不明白。谁能解释一下?
modifyDate 是应用 API 返回的类日期对象。我已将其转换为字符串,看起来像预期的那样(对我来说是 EST)。因此,使用 Calendar 和 SimpleDateFormat 将其转换为特定格式的字符串,我可以在 SQL 更新语句中使用 UTC 字符串将其发送到数据库。
注意:我正在将调试语句写入由应用程序而不是标准输出生成的批处理作业日志文件。是的,有更好的方法,但这应该是一个快速的小部件。
//adjust modify date for UTC to send to database
String dfcDatePattern = "mm/dd/yyyy hh:mi:ss";
String javaDatePattern = "MM/dd/yyyy HH:mm:ss";
String oracleDatePattern = "MM/DD/YYYY HH24:MI:SS";
String strModifyDate = modifyDate.asString(dfcDatePattern);
if (m_debugMode) m_File.writeBytes("DFC Modify Date String: " + strModifyDate + NEWLINE);
TimeZone localTimeZone = TimeZone.getDefault();
TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
GregorianCalendar cal = new GregorianCalendar();
cal.setTimeZone(localTimeZone);
if (m_debugMode) m_File.writeBytes("DFC Year: " + modifyDate.getYear() + NEWLINE);
if (m_debugMode) m_File.writeBytes("DFC Month: " + modifyDate.getMonth() + NEWLINE);
if (m_debugMode) m_File.writeBytes("DFC Day: " + modifyDate.getDay() + NEWLINE);
if (m_debugMode) m_File.writeBytes("DFC Hour: " + modifyDate.getHour() + NEWLINE);
if (m_debugMode) m_File.writeBytes("DFC Minutes: " + modifyDate.getMinutes() + NEWLINE);
if (m_debugMode) m_File.writeBytes("DFC Seconds: " + modifyDate.getSeconds() + NEWLINE);
cal.set(modifyDate.getYear(), modifyDate.getMonth(), modifyDate.getDay(), modifyDate.getHour(), modifyDate.getMinutes(), modifyDate.getSeconds());
if (m_debugMode) m_File.writeBytes("Converted Modify Date: " + cal.toString() + NEWLINE);
SimpleDateFormat sdf = new SimpleDateFormat(javaDatePattern);
if (m_debugMode) m_File.writeBytes("Modify Date in Local Time Zone: " + sdf.format(cal.getTime()) + NEWLINE);
sdf.setTimeZone(utcTimeZone);
if (m_debugMode) m_File.writeBytes("Modify Date in UTC Time Zone: " + sdf.format(cal.getTime()) + NEWLINE);
updateQueryString = "execute exec_sql with query = 'update dm_sysobject_s set r_modify_date = TO_DATE(''" + sdf.format(cal.getTime()) + "'',''" + oracleDatePattern + "'') where r_object_id = ''" + objectIdString + "'' '";
输出:
DFC Modify Date String: 03/30/2016 11:44:30 [yep, looks good]
DFC Year: 2016
DFC Month: 3 [month looks good here]
DFC Day: 30
DFC Hour: 11 [EST hour]
DFC Minutes: 44
DFC Seconds: 30
[是的,每个部分看起来都不错]
Converted Modify Date: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=3,WEEK_OF_YEAR=14,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=90,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=3,HOUR_OF_DAY=11,MINUTE=44,SECOND=30,MILLISECOND=399,ZONE_OFFSET=-18000000,DST_OFFSET=3600000]
[转储这个看看我是否能弄清楚发生了什么。我认为一切看起来都不错]
Modify Date in Local Time Zone: 04/30/2016 11:44:30
[不好!时间是正确的,但它增加了一个月!? UTC 偏移量只有 4 小时!]
Modify Date in UTC Time Zone: 04/30/2016 15:44:30
[不好!时间按预期正确调整,但仍增加了一个月]
exec_sql to update r_modify_date: execute exec_sql with query = 'update dm_sysobject_s set r_modify_date = TO_DATE(''04/30/2016 15:44:30'',''MM/DD/YYYY HH24:MI:SS'') where r_object_id = ''09ae12f980002934'' '
[这就是我想要的 SQL 的样子;同一天,但时间已根据 UTC 偏移量进行了调整。但是这个月是关闭的。 SQL 语法很好(由于 API 语法看起来很奇怪);它更新数据库中的记录;只是月份错误。]
我想我可以通过增加四个小时来强制硬编码偏移量,但我认为以上是“正确”的方式。为什么它不起作用?
【问题讨论】:
-
我相信 java.util.GregorianCalendar 的月份是从零开始的,所以 3 是四月,而不是三月
-
天啊。我没有想到。在 javadoc 中确认:公历和儒略历中的第一个月是 JANUARY,即 0。非常感谢;正在拉我的头发。
-
另外,我向您以编程方式而不是蛮力处理时区的努力表示敬意。以我的经验,这是一个通常会得到回报的麻烦。