1

我们正在尝试解释存储在 Axapata 的 TIMEZONESRULESDATA 表中的数据。特别是,我们想弄清楚它如何存储 DST 开始/结束时间。到目前为止,我的猜测是:

TZENUM:外键引用 TIMEZONESLIST(时区名称和标识符)
YEAR:0 如果规则无限期有效或时区规则生效的年份
BIAS:以分钟为单位的 UTC 时间
偏移 DBIAS:DST 的偏移(添加到 BIAS 以获得与 UTC 的总偏移量)

现在对于我不明白的部分:

DYEAR,DMONTH,DDAYOFWEEK,DDAY,DHOUR,DMINUTE,DSECOND
SYEAR,SMONTH,SDAYOFWEEK,SDAY,SHOUR,SMINUTE,SECOND

我会从日期猜测 D* 是 DST 的开始日期,而 S* 是结束日期。但是,我不明白为什么它需要一年和星期几字段。此外,*DAY 似乎并不表示月份中的哪一天 - 至少它不表示切换 DST 的正确日期。它似乎也不对应于 Axapta 自己的 DateTimeUtil 或 Form 自动转换转换日期的日期。

有谁知道如何解释这张表?或者我在哪里可以查到?

索伦

4

3 回答 3

1

DDAYSDAY 看起来像是表示月份中的第几周,但后来我们发现DDAY - 和SDAY - 值分别为 6、23或 28。这些是一年中的几周,还是个别日子的值 > 5 被劫持?

我的理论是这样的:在DMONTH = 8 和DDAYOFWEEK = 6 的情况下,我们有

  • DDAY = 4 ==> 8 月的第 4 个星期六
  • DDAY = 5 ==> 八月的最后一个星期六
  • DDAY = n > 5 ==> 8 月 n 日(可能与 DDAYOFWEEK 发生冲突?)

那么大于 5的SDAYDDAY是什么?

于 2009-08-18T11:22:14.173 回答
0

DDAYSDAY代表一个月中的一周(1-4、5 = 上周)

DDAYOFWEEKSDAYOFWEEK代表星期几(0 = 星期日)

您将如何使用这些信息?

于 2009-08-12T14:39:14.273 回答
0

我编写了两个 SQL 函数来将 Dynamics AX UTC 日期从 TIMEZONESRULESDATA 表转换为适当的时区日期/时间。它们似乎在我测试过的场景中工作,但我很高兴得到反馈。

第一个函数从任何 AX 表中获取 UTC 日期时间和 TZID,并生成带有任何夏令时调整的时区中的日期/时间:

-- *** IMPORTANT NOTE: @@DATEFIRST must be 7 for this to work ***
CREATE FUNCTION [dbo].[ConvertUTCDateTime] (@DateTime DATETIME, @TZID INT)
RETURNS DATETIME
AS
BEGIN

DECLARE @AdjustedDateTime DATETIME
SET @AdjustedDateTime=@DateTime

-- Fields to be extracted from TIMEZONESRULESDATA record for TZID
DECLARE @Bias INT, @DBias INT
DECLARE @DMonth INT, @DDayOfWeek INT, @DDay INT, @DHour INT, @DMinute INT, @DSecond INT     -- Start of Daylight Saving
DECLARE @SMonth INT, @SDayOfWeek INT, @SDay INT, @SHour INT, @SMinute INT, @SSecond INT     -- End of Daylight Saving
-- Daylight Saving Date/Time ranges
DECLARE @DSTFromDateTime1 DATETIME, @DSTToDateTime1 DATETIME, @DSTFromDateTime2 DATETIME, @DSTToDateTime2 DATETIME

SELECT
    @Bias=tzr.BIAS,@DBias=tzr.DBIAS,
    @DMonth=tzr.DMONTH, @DDayOfWeek=tzr.DDAYOFWEEK, @DDay=tzr.DDAY, @DHour=tzr.DHOUR, @DMinute=tzr.DMINUTE, @DSecond=tzr.DSECOND,
    @SMonth=tzr.SMONTH, @SDayOfWeek=tzr.SDAYOFWEEK, @SDay=tzr.SDAY, @SHour=tzr.SHOUR, @SMinute=tzr.SMINUTE, @SSecond=tzr.SSECOND
FROM MyAXDatabase..TIMEZONESRULESDATA tzr
WHERE tzr.RULEID=@TZID

IF @Bias IS NOT NULL
    BEGIN
        SET @AdjustedDateTime=DATEADD(MINUTE, (-1)*@Bias, @DateTime )       -- Standard Time Zone Adjustment from UTC
        IF @DMonth>0    -- If there is Daylight Saving
            BEGIN
                SET @DSTFromDateTime1=dbo.GetDSTDateTime(@AdjustedDateTime, @DMonth, @DDayOfWeek, @DDay, @DHour, @DMinute, @DSecond )   -- Get DS Start date in year
                SET @DSTToDateTime2=dbo.GetDSTDateTime(@AdjustedDateTime, @SMonth, @SDayOfWeek, @SDay, @SHour, @SMinute, @SSecond ) -- Get DS End date in year
                IF @DSTFromDateTime1>@DSTToDateTime2
                    BEGIN
                        SET @DSTToDateTime1= DATEADD(SECOND, -1, CAST(DATEFROMPARTS( YEAR(@AdjustedDateTime)+1, 1, 1) as DATETIME)) -- End of Current Year
                        SET @DSTFromDateTime2= DATEFROMPARTS( YEAR(@AdjustedDateTime), 1, 1)                        -- Start of Current Year
                    END
                ELSE
                    BEGIN
                        SET @DSTToDateTime1=@DSTToDateTime2
                        SET @DSTFromDateTime2=@DSTFromDateTime1
                    END
                IF @AdjustedDateTime BETWEEN @DSTFromDateTime1 AND @DSTToDateTime1 
                    OR @AdjustedDateTime BETWEEN @DSTFromDateTime2 AND @DSTToDateTime2
                    SET @AdjustedDateTime=DATEADD(MINUTE, (-1)*@DBias, @AdjustedDateTime )  -- Make Daylight Saving adjustment if in DST date range
            END
    END

RETURN @AdjustedDateTime

END

第二个函数根据 TIMEZONESRULESDATA 字段提供的参数计算夏令时开始或结束日期:

-- *** IMPORTANT NOTE: @@DATEFIRST must be 7 for this to work ***
CREATE FUNCTION [dbo].[GetDSTDateTime](
@DateTime DATETIME,     -- Base Date
@Month INT,         -- Month for Start/End of DST
@DayOfWeek INT,         -- Day of Week  0=Sun..6=Sat (based on coding in TIMEZONESRULESDATA table)
@Day INT,           -- Week of the Month (confusing?!) 1-5 ; 5 means last week
@Hour INT, 
@Minute INT, 
@Second INT
) RETURNS DATETIME
AS
BEGIN

DECLARE @MyDateTime DATETIME

SET @MyDateTime=DATEFROMPARTS( YEAR(@DateTime), @Month, 1) -- First day of DST Start/End Month from @BaseDate year
SET @DayOfWeek=@DayOfWeek + 1   -- Adjust to tie in with SQL DoW 1-7

-- Establish first selected DayOfWeek in the month
IF @DayOfWeek >= DATEPART(WEEKDAY, @MyDateTime )
    SET @MyDateTime=DATEADD(DAY, @DayOfWeek - DATEPART(WEEKDAY, @MyDateTime), @MyDateTime)
ELSE
    SET @MyDateTime=DATEADD(DAY, 7-(DATEPART(WEEKDAY, @MyDateTime) - @DayOfWeek), @MyDateTime)

-- Add the appropriate number of weeks
SET @MyDateTime=DATEADD(DAY, 7*(@Day-1), @MyDateTime)

-- For last week of month ensure that date is in correct month
WHILE MONTH(@MyDateTime)<>@Month
    BEGIN
        SET @MyDateTime=DATEADD(DAY, -7, @MyDateTime)
    END;

-- Add on Hours, Minutes and Seconds
SET @MyDateTime=DATEADD(SECOND, @Second, DATEADD(MINUTE, @Minute, DATEADD(HOUR, @Hour, @MyDateTime)))

RETURN @MyDateTime

END
于 2016-11-24T13:15:06.453 回答