由于时区和使用SystemDateGet()而发布日期问题

时间:2011-12-08 04:00:35

标签: timezone axapta dynamics-ax-2009 x++

摘要

我们遇到了systemDateGet()函数返回的问题 AOS在确定发布日期时需要本地日期。

详情

  • 我们在世界各地都有分支机构,国际日期线的两边都有 用户使用适当的时区设置连接到本地终端服务器 为用户的分支。

  • 每个分支都与已配置的其他公司相关联 正确的时区。

  • 我们运行一个AOS,并为总部设置时区设置。有 不是引入额外AOS的选择。

  • SystemDateGet()函数在用户未更改时返回AOS日期 他们的Axapta会议日期。

  • 数据库中与发布日期相关的许多系统字段都是基于DATE的 不是基于UTCDATETIME。

  • 我们正在运行AX2009 SP1 RU7。

    • 内核版本5.0.1500.4570
    • 应用程序版本5.0.1500.4570
    • 本地化版本:巴西,中国,日本,泰国,印度
  • 我知道SystemDateGet()函数被设计为返回AOS日期,除非 用户更改其会话日期,在这种情况下返回日期。

  • 每个用户都在用户个人资料中设置了适当的时区。

问题

问题的一个例子是当用户试图发布涉及金融的期刊时 交易,检查分类账期间是否开放。例如, 该用户是在英国试图在11月30日下午3点在当地发布期刊 时间,标准Axapta代码使用systemDateGet()函数来确定要使用的日期 在验证中(确定期间是否开放)。在我们的案例中,AOS的基础是 澳大利亚布里斯班和systemDateGet()函数将于12月1日返回 (当地时间12月1日凌晨1点)。

问题的另一个例子是发票在星期五在美国发布 AOS所在的星期几是星期六。我们需要系统 记录当地日期。

问题

除了重写涉及systemDateGet()的所有系统代码之外,还有超过2000个实体 任何其他可用于解决获取正确本地问题的选项 日期?

解决方案限制。

  • 在上面给出的分类账周期关闭的例子中,不可能从a 商业实践的立场是在月末处理之前开启下一个时期 已经完成。

  • 目前无法购买额外的AOS。

2 个答案:

答案 0 :(得分:1)

Global类中创建一个函数:

static date systemDateGetLocal()
{
    return DateTimeUtil::date(DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::utcNow(), DateTimeUtil::getUserPreferredTimeZone()));
}

然后在Info.watchDog()做一个:

systemDateSet(systemDateGetLocal());

这可能只是部分解决方案,watchDog仅在客户端执行。

答案 1 :(得分:0)

这是一个快速更新。如果有任何问题或情况需要解决,请告诉我。

使用当地时间

<强>简介
以下是正在进行的更新,因为该解决方案尚未在所有情况下进行全面测试。

<强>问题:
如果用户与AOS具有不同的时区,则timeNow()和systemDateGet()函数将在需要本地日期时间时返回AOS详细信息。

<强>澄清器:
当在Axapta中更改本地日期时间时,systemDateGet()函数将返回本地日期,但timeNow()函数仍返回AOS时间。

编码更改:
已经进行了许多编码改变以处理许多不同的情况。如果需要说明,将添加评论。

括号更改为{和}以允许发布。

CLASS:GLOBAL

我给出的一个要求是允许系统处理可能具有不同时区的公司内的多个站点。目前,此功能不是必需的。

static server void setSessionDateTime(
    inventSiteId    inventSiteId = '', 
    utcDateTime     reference = dateTimeUtil::utcNow())
{
    str                             sql;
    sqlStatementExecutePermission   perm;
    connection                      conn        = new UserConnection();
    timeZone                        timeZone;
    int                             ret;
    ;

    if (inventSiteId)
    {
        timeZone = inventSite::find(inventSiteId).Timezone;
    }
    else
    {
        timeZone = dateTimeUtil::getCompanyTimeZone();
    }

    //This is to get around the kernel validation of changing timezones
    //when the user has more than one session open.

    sql     = strfmt("Update userInfo set preferredTimeZone = %1 where userInfo.id = '%2'", enum2int(timeZone), curUserId());
    perm    = new SQLStatementExecutePermission(sql);
    perm.assert();

    ret = conn.createStatement().executeUpdate(sql);

    dateTimeUtil::setUserPreferredTimeZone(timeZone);
    dateTimeUtil::setSystemDateTime(reference);

    CodeAccessPermission::revertAssert();
}

static int localTime()
{
    utcDateTime tmp;
    ;
    setSessionDateTime();

    tmp = dateTimeUtil::applyTimeZoneOffset( dateTimeUtil::utcNow(), dateTimeUtil::getCompanyTimeZone());
    return dateTimeUtil::time(tmp);
}

以下方法作为交叉检查实施,以确保systemDateGet()返回预期值。

static date localDate()
{
    utcDateTime tmp;
    ;
    setSessionDateTime();

    tmp = dateTimeUtil::applyTimeZoneOffset( dateTimeUtil::utcNow(), dateTimeUtil::getCompanyTimeZone());
    return dateTimeUtil::date(tmp);
}

CLASS:APPLICATION

修改方法setDefaultCompany。超级通话后直接添加行setSessionDateTime();。这是为了在用户更换公司时允许更改时间(我给出了另一项要求)。

CLASS:INFO

以便系统从会话开始使用正确的日期/时间。

void startupPost()
{
    ;
    setSessionDateTime();
}

修改方法canViewAlertInbox(),将第setSessionDateTime();行添加为第一行。这是为了处理用户是否有为不同公司开放的多个表单。

与本地化相关的更改:

根据您的Service Pack和本地化,您需要更改对象的功能以使用localTime()函数,替换timeNow()。重要说明:请勿更改BatchRun类以使用新的localTime函数,因为这将使其停止正常工作。

在我们的系统中,大约有260个实例可以更改。如果不使用所有模块和本地化,则需要更改的实际行数将会减少。

最后说明:

代码中有许多today()调用。我还没有通过每一行来确保它被正确编码,即使用today()而不是systemDateGet()。

已知问题:

我遇到过时区更改功能无法按预期完成的情况。这是一个会话正在进行数据库同步而另一个会话在另一个公司中打开的时候。由于普通用户永远无法做到这一点,我现阶段没有花太多时间在其解决方案上。这是我打算解决的问题。