简体   繁体   English

为什么在添加 DAYLIGHT SAVING TIME 时 CONVERT DATE 会因 sy-subrc 12 而失败?

[英]Why does CONVERT DATE fail with sy-subrc 12 when adding DAYLIGHT SAVING TIME?

The following code fails with sy-subrc=12 .以下代码因sy-subrc=12而失败。

CONVERT DATE '20191105'
    TIME '123000'
    DAYLIGHT SAVING TIME 'X'
    INTO TIME STAMP DATA(timestamp)
    TIME ZONE 'CET   '.

In the ABAP documentation it says:ABAP 文档中它说:

12: The specified time could not be converted, because dat, tim, or dst contain invalid or inconsistent values. 12:无法转换指定的时间,因为 dat、tim 或 dst 包含无效或不一致的值。

I noticed that when I remove the 'X' in sy-dayst in the debugger it does the conversion.我注意到,当我在调试器中删除 sy-dayst 中的“X”时,它会进行转换。

But of course I want to take daylight savings into consideration so how can I make this work?但是我当然想考虑夏令时,所以我怎样才能做到这一点?

So you mean I don't need to pass DAYLIGHT SAVING TIME because CET will cause the Date to convert the correct way already?所以你的意思是我不需要通过 DAYLIGHT SAVING TIME 因为 CET 会导致 Date 已经以正确的方式转换?

tl;dr : Yes, the CONVERT DATE command automatically takes care of DST (at least for timezone CET ). tl;dr :是的, CONVERT DATE命令会自动处理 DST(至少对于时区CET )。 The sy-subrc==12 ist set for illegal arguments. sy-subrc==12设置为非法 arguments。

Here's a minimal program for your snippet that covers all the edge cases.这是一个涵盖所有边缘情况的代码片段的最小程序。 I added the resulting timestamps in a readable format (manually edited) in the comments.我在评论中以可读格式(手动编辑)添加了生成的时间戳。

CONVERT DATE '20190101' TIME '000000' "" // german 'winter time' (no DST, GMT+1)
        INTO TIME STAMP DATA(timestamp0) "" // 2018-12-31T23:00:00Z
        TIME ZONE 'CET   '.

CONVERT DATE '20190701' TIME '000000' "" // german 'summer time' (DST, GMT+2)
        INTO TIME STAMP DATA(timestamp1) "" // 2019-06-30T22:00:00Z
        TIME ZONE 'CET   '.

CONVERT DATE '20190331' TIME '015959' "" // last second before non DST (GMT+1) ==> DST (GMT+2) transition
        INTO TIME STAMP DATA(timestamp2) "" // 2019-03-31T00:59:59
        TIME ZONE 'CET   '.

CONVERT DATE '20190331' TIME '023000' "" // local time does not exist in germany, it's skipped
        INTO TIME STAMP DATA(timestamp3) "" // '0' <-- is this initial?
        TIME ZONE 'CET   '.
""// sy-subrc == 12 here!

CONVERT DATE '20190331' TIME '030000' "" // first second of german DST (GMT+2)
        INTO TIME STAMP DATA(timestamp4) "" // 2019-03-31T01:00:00Z
        TIME ZONE 'CET   '.

CONVERT DATE '20191027' TIME '015959' "" // last second before SAP undefined time range (turn your system off now)
        INTO TIME STAMP DATA(timestamp5) ""// 2019-10-26T23:59:59Z
        TIME ZONE 'CET   '.

CONVERT DATE '20191027' TIME '023000' "" // in the undefined zone, could theoretically be both DST and non-DST
        INTO TIME STAMP DATA(timestamp6) "" 2019-10-27T00:30:00Z <-- but is treated as DST
        TIME ZONE 'CET   '.

CONVERT DATE '20191027' TIME '030000' "" // first second in non DST time (german winter, GMT+1 again)
        INTO TIME STAMP DATA(timestamp7) "" 2019-10-27T02:00:01Z
        TIME ZONE 'CET   '.

There a reason why modern programming languages handle datetime objects as something more complex than just 8 or 14 numeric character long strings.现代编程语言将日期时间对象处理为比 8 或 14 个数字字符长字符串更复杂的东西是有原因的。 Dealing with different timezones and local vs. UTC data is annoying in ABAP because most of the SAP tables and dependent function modules and classes randomly assume that stored dates and times are either in UTC or local time (which is not even unique in case of DST!)在 ABAP 中处理不同的时区和本地与 UTC 数据很烦人,因为大多数 SAP 表和相关的 function 模块和类随机假设存储的日期和时间是 UTC 或本地时间(这在 DST 的情况下甚至不是唯一的!)

TL;DR TL;博士

Never use DAYLIGHT SAVING TIME (except in very special cases if you're expert)切勿使用DAYLIGHT SAVING TIME (如果您是专家,则在非常特殊的情况下除外)

And well said by @konstantin: @konstantin 说得好:

"CONVERT DATE command automatically takes care of DST" “CONVERT DATE 命令自动处理 DST”

Explanation:解释:

DAYLIGHT SAVING TIME 'X' can be used only if the local time (DATE and TIME) matches the one-hour (rarely two hours) interval to switch from summer time to winter time, for the given time zone (note that some time zones have no daylight saving time). DAYLIGHT SAVING TIME 'X'仅当本地时间(日期和时间)与给定时区的一小时(很少是两小时)间隔以从夏令时切换到冬令时匹配时才能使用(请注意,某些时区没有夏令时)。

For instance, in 2003, Brazil switched to the winter time on March 9th (Sunday) at 2am;例如,2003 年,巴西在 3 月 9 日(星期日)凌晨 2 点切换到冬季时间; at 2am, the clocks had to be moved back one hour to 1am, and consequently 1:30am occured twice.凌晨 2 点,时钟不得不拨回一小时到凌晨 1 点,因此凌晨 1 点 30 分出现了两次。

So, if ABAP has to convert the local time 2003/03/09 01:30:00 to the UTC time, it has to know if the local time is during the daylight saving time (winter time) or not (summer time), which respectively correspond to the UTC times 2003/03/09 03:30:00 or 2003/03/09 04:30:00.因此,如果 ABAP 必须将本地时间 2003/03/09 01:30:00 转换为 UTC 时间,它必须知道本地时间是否在夏令时(冬令时)或不在夏令时(夏令时),分别对应 UTC 时间 2003/03/09 03:30:00 或 2003/03/09 04:30:00。

Demonstration:示范:

DATA: time_stamp TYPE timestamp,
      dat TYPE d,
      tim TYPE t,
      tz  TYPE ttzz-tzone.

tz = 'BRAZIL'. "UTC-03:00
dat = '20030309'.
tim = '013000'.

CONVERT DATE dat TIME tim DAYLIGHT SAVING TIME 'X' " winter time
        INTO TIME STAMP time_stamp TIME ZONE tz.
ASSERT time_stamp = '20030309033000'. " UTC time

CONVERT DATE dat TIME tim DAYLIGHT SAVING TIME ' ' " summer time
        INTO TIME STAMP time_stamp TIME ZONE tz.
ASSERT time_stamp = '20030309043000'. " UTC time

Now, the question is, how to know whether DAYLIGHT SAVING TIME 'X' has to be used or not.现在,问题是,如何知道是否必须使用DAYLIGHT SAVING TIME 'X' In fact, if a database table contains the local time I used in the example above, one can't know whether it's summer time or winter time because the daylight saving time is never assigned to a table column along with the date and time columns.事实上,如果一个数据库表包含我在上面示例中使用的本地时间,则无法知道它是夏令时还是冬令时,因为夏令时从未与日期和时间列一起分配给表列。


That's why SAP has introduced a solution, ~10 years ago, which made DAYLIGHT SAVING TIME almost obsolete.这就是SAP 在大约 10 年前推出的解决方案的原因,该解决方案使DAYLIGHT SAVING TIME几乎过时。 The actual problem was not the daylight saving time but the non-continuous time which could lead to issues like chronological sorting.实际问题不是夏令时,而是可能导致时间排序等问题的非连续时间。 The principle of the solution is to slow down the time during the daylight saving time switch, so that one given time never occurs twice and the time remains continuous.解决的原理是在夏令时切换过程中将时间放慢,这样一个给定的时间就不会出现两次,并且时间保持连续。 Technically, it affects the system variables SY-DATUM (date) and SY-UZEIT (time).从技术上讲,它会影响系统变量SY-DATUM (日期)和SY-UZEIT (时间)。 In this "double hour" interval, two real seconds are needed to make one SAP second.在这个“双小时”间隔中,需要两个实际秒才能产生一个 SAP 秒。 This behavior is activated by default (value "on") via the profile parameter zdate/DSTswitch_contloctime which you may view via the transaction code RZ11 .默认情况下(值“on”)通过配置文件参数zdate/DSTswitch_contloctime激活此行为,您可以通过事务代码RZ11 Below is the SAP time according to the old ("off") or new way ("on"), if the switch occurs at local time 2am (with "on", you don't see the switch):下面是根据旧(“off”)或新方式(“on”)的 SAP 时间,如果切换发生在当地时间凌晨 2 点(使用“on”,则看不到切换):

off: 1:00, 1:30, 1:00, 1:30, 2:00
on : 1:00, 1:15, 1:30, 1:45, 2:00

Just to add complexity, note that CONVERT still have a one-hour gap.只是为了增加复杂性,请注意CONVERT仍然有一个小时的差距。 For example, with zdate/DSTswitch_contloctime set to "on" and without DAYLIGHT SAVING TIME , CONVERT will give these UTC timestamps respectively, there is a gap of one hour between 03:59:59 and 05:00:00:例如,当zdate/DSTswitch_contloctime设置为“on”并且没有DAYLIGHT SAVING TIMECONVERT将分别给出这些 UTC 时间戳,在 03:59:59 和 05:00:00 之间有一个小时的间隔:

3:00, 3:15, 3:30, 3:45, 5:00

But this gap is not a big drawback, compared to the risk of having chronological sort issues.但与出现时间排序问题的风险相比,这种差距并不是一个大缺点。

More information: https://blogs.sap.com/2009/12/09/daylight-saving-time-and-slowing-down-the-time/ and SAP note 950114 - Profile parameter zdate/DSTswitch_contloctime .更多信息: https://blogs.sap.com/2009/12/09/daylight-saving-time-and-slowing-down-the-time/SAP note 950114 - Profile parameter zdate/DSTswitch_contloctime


Note that SY-DAYST corresponds to the DST indicator of the current time of the application server ( SY-DATUM , SY-UZEIT , and time zone being defined in table TTZCU ).请注意, SY-DAYST对应于应用程序服务器当前时间的 DST 指示符( SY-DATUMSY-UZEIT和表TTZCU中定义的时区)。 I don't see any possible usage of it.我看不出它有任何可能的用途。 If you want to convert a time which was initially obtained with SY-DATUM and SY-UZEIT , into a UTC time stamp, you should use the method SYSTEMTSTMP_SYST2UTC of class CL_ABAP_TSTMP .如果要将最初使用SY-DATUMSY-UZEIT获得的时间转换为 UTC 时间戳,则应使用SYSTEMTSTMP_SYST2UTCCL_ABAP_TSTMP方法。 Example to get the current time:获取当前时间的示例:

cl_abap_tstmp=>systemtstmp_syst2utc(
  EXPORTING
    syst_date = sy-datum
    syst_time = sy-uzeit
  IMPORTING
    utc_tstmp = DATA(now_utc) ).

As @konstantin demonstrated (" DATE '20190331' TIME '023000' [...] local time does not exist in germany" ), CONVERT DATE without DAYLIGHT SAVING TIME may return sy-subrc=12 in rare occasions, if the input date and time correspond to something inside the "vanishing hour" due to the switch from winter time to summer time the if the time zone has DST.正如@konstantin 所展示的(“ DATE '20190331' TIME '023000' [...] local time 在德国不存在” ),如果输入日期, CONVERT DATE without DAYLIGHT SAVING TIME在极少数情况下可能会返回sy-subrc=12如果时区有 DST,由于从冬季时间切换到夏季时间,时间对应于“消失时间”内的某些内容。 For instance: "at 2am, it is 3am", the local time "2:30am" doesn't exist at all.例如:“at 2am, it is 3am”,当地时间“2:30am”根本不存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM