- 
                Notifications
    
You must be signed in to change notification settings  - Fork 743
 
重构服务器重置时间处理 #2160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
重构服务器重置时间处理 #2160
Conversation
simplify GetNextWeeklyResetTime logic
assert day of week for arrange variable for clarity
| 
           我觉的现在使用本地时区的方式应该不会出现什么问题,你新增的方式还会造成额外的配置成本。 I think using the local time zone now should not cause any problems, and the new method you added will also result in additional configuration costs.  | 
    
| 
           Hmm... In that case, is there a way to get the tasks to correctly check for the server reset time if I am in a different time zone than the server? For example, if I am in GMT+7 but the Asia server is on GMT+8, the server resets at 3 AM my local time (which is 4 AM server time). However, the 'Blessing of the Welkin Moon' task is triggered based on my local time ( better-genshin-impact/BetterGenshinImpact/GameTask/Common/Job/BlessingOfTheWelkinMoonTask.cs Line 24 in b731a87 
 Similarly, some tasks depend on a specific  
 If there is a simpler way to handle this without adding configuration, please enlighten me. I understand that changing the system timezone to match the server is a workaround, but it would be much more convenient not to have to. 嗯... 既然如此,那有没有办法让我在不同于服务器的时区时,任务也能正确检查服务器的重置时间呢? 举个例子,如果我在 GMT+7 时区,而亚洲服务器在 GMT+8 时区,那么服务器是在我的本地时间凌晨3点重置(也就是服务器时间的早上4点)。然而,‘空月祝福’任务是根据我的本地时间触发的( better-genshin-impact/BetterGenshinImpact/GameTask/Common/Job/BlessingOfTheWelkinMoonTask.cs Line 24 in b731a87 
 同样,有些任务依赖于特定的 
 如果有一个更简单的方法来解决这个问题,而无需增加配置项,请指点我一下。我明白将系统时区改为与服务器一致是一个解决办法,但如果能不这么做,肯定会方便很多。  | 
    
| 
           鸭蛋忙得混乱了╮(╯▽╰)╭  | 
    
| 
           At first, I thought it would be better to give users more control. My reasoning was that if someone needed to change their system time manually for some reason, allowing a custom server reset time configuration would be helpful. But if that's not the desired approach, then having a configuration for server region selection and simply inferring the time offset from that would probably be sufficient. I can try to refactor the code to meet that goal if you would like my help. However, if a core developer plans to implement this, then I will be happy to just use a workaround in the meantime. 起初,我认为给用户更多控制权会更好。我的想法是,如果有人出于某些原因需要手动更改系统时间,那么允许自定义服务器重置时间的配置会很有用。 但如果这不是项目的首选方案,那么提供一个服务器区域选择的配置项,然后据此推断时间偏移量,可能就足够了。 如果你需要我的帮助,我可以尝试朝这个目标重构代码。不过,如果核心开发者打算自己来实现这个功能,那么我很乐意暂时先使用一个变通方案。  | 
    
| 
           奥,我的问题。那确实只能通过设置来解决。  
看上去同类软件有不错的处理方案,不过针对夏令时还是很麻烦。可能需要引入第三方库来解决,比如 https://github.com/nodatime/nodatime  | 
    
| 
           Understood. To confirm, the goal is to keep the logic server-time-based inline, like  If so, NodaTime might be overkill. We can convert UTC to the fixed server timezone (no DST). For example: // Pseudo-code: Get UTC now, convert to hardcoded server timezone
DateTimeOffset serverTime = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(8)); // Asia
if (serverTime.Hour == 4 && serverTime.DayOfWeek == DayOfWeek.Monday) {
    // Reset logic
}// Get the TimeZoneInfo object based on the selected server region
TimeZoneInfo serverTimeZone = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
DateTime serverTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, serverTimeZone);
// The rest of the logic is the same
if (serverTime.Hour == 4) {
    // Logic for 4 AM reset
}Both the servers and UTC time are not affected by Daylight Saving Time. 明白了。确认一下,目标是让代码逻辑保持基于服务器时间并内联,比如  如果这样,NodaTime 可能太重了。我们可以将 UTC 时间转换为固定的服务器时区(无夏令时)。例如: // 示例:获取当前UTC时间,转换为硬编码的服务器时区
DateTimeOffset serverTime = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(8)); // 亚服
if (serverTime.Hour == 4 && serverTime.DayOfWeek == DayOfWeek.Monday) {
    // 重置逻辑
}// 根据所选服务器区域获取 TimeZoneInfo 对象
TimeZoneInfo serverTimeZone = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
DateTime serverTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, serverTimeZone);
// 接下来的逻辑与之前相同
if (serverTime.Hour == 4) {
    // 凌晨4点重置的逻辑
}服务器和 UTC 时间均不受夏令时的影响。  | 
    
| 
           也就是说原神服务器均不受夏令时影响?  | 
    
          
 用有限的地理知识想了一下:除非玩家大部分都住在高维度地区,否则服务器没道理用夏令时吧  | 
    
| 
           Yes, Genshin Impact servers use fixed timezone offsets and do not observe Daylight Saving Time (DST). DST is a feature of specific regional timezones (like US PST/PDT) that alters the local system clock. This inherent variability of local time is the core issue with using DateTime.Now. Using the fixed reference of UTC would resolve this. 没错,原神服务器使用的是固定的时区偏移,不实行夏令时(DST)。DST是某些地区性时区(如美国的PST/PDT)的特性,它会改变本地系统时钟。本地时间的这种固有可变性,正是在代码中使用 DateTime.Now 的核心问题。使用固定的UTC时间基准就可以解决这个问题。  | 
    
| 
           These files internally hard-code server reset logic. This is obvious enough to me, and they have been refactored to use the server region timezone offset setting: 
 These files are candidates for refactoring but it's dubious whether they are supposed to follow server time or local time. They may also require user time input that could be misinterpreted as local time. (Search for type  
 The refactored code lines are commented for comparison and can be deleted after review. 这些文件在内部硬编码了服务器重置逻辑,这一点对我来说非常明显,并且它们已经被重构以使用服务器区域时区偏移设置: 
 这些文件是待重构的候选,但不明确它们到底应该遵循服务器时间还是本地时间,或者是否需要用户输入可能被误解为本地时间的时间。(可以在 IDE 中搜索类型  
 重构后的代码行已添加注释以供比较,可以在审查后删除。  | 
    
| 
           I think the server's regional time or its offset needs to be exposed to the JS scripts. Currently, most scripts weren't made to handle different server regions. They often use  A JavaScript  There seem to be two ways to solve this: 
 我认为服务器的区域时间或其偏移量需要暴露给 JS 脚本。 目前,大多数脚本在设计时没有考虑不同的服务器区域。它们经常使用  JavaScript 的  似乎有两种方法可以解决这个问题: 
  | 
    
return local DateTimeOffset for eaiser testing without Config
| 
           I'm working on abstracting time access to use  I've created a simple interface and implementation to replace the  public interface IServerTimeProvider
{
    DateTimeOffset GetServerTimeNow();
}
public class ServerTimeProvider(TimeProvider timeProvider) : IServerTimeProvider
{
    public DateTimeOffset GetServerTimeNow()
    {
        TimeSpan serverOffset;
        try
        {
            serverOffset = TaskContext.Instance().Config.OtherConfig.ServerTimeZoneOffset;
        }
        catch (Exception)
        {
            serverOffset = TimeSpan.FromHours(8);
        }
        return timeProvider.GetUtcNow().ToOffset(serverOffset);
    }
}However, I've hit an architectural question. The method  We have a few options: 
 I need your input on the preferred approach for handling these kinds of cases where time logic exists in classes that shouldn't have dependencies injected into them. 我正在按照您的建议,尝试抽象化时间访问以使用  我创建了一个简单的接口和实现来替换  public interface IServerTimeProvider
{
    DateTimeOffset GetServerTimeNow();
}
public class ServerTimeProvider(TimeProvider timeProvider) : IServerTimeProvider
{
    public DateTimeOffset GetServerTimeNow()
    {
        TimeSpan serverOffset;
        try
        {
            serverOffset = TaskContext.Instance().Config.OtherConfig.ServerTimeZoneOffset;
        }
        catch (Exception)
        {
            serverOffset = TimeSpan.FromHours(8);
        }
        return timeProvider.GetUtcNow().ToOffset(serverOffset);
    }
}但是,我遇到了一个架构上的问题。 我们有几个选择: 
 我需要您就如何处理这类情况提供意见,即时间逻辑存在于不应直接注入依赖的类中。  | 
    
          
 你说的对,构造函数注入这里不适用了,即使提供一个无参构造函数或者强行指定构造函数,Json反序列化后还是得为对象手动补上依赖服务,更何况它最终还是ViewModel的成员,要补只能在ViewModel的Command中,调用  | 
    
| 
           终于有人做了,太棒了。 I've been waiting for this for so long, and someone actually submitted a PR. I'm so touched!  | 
    
…ly keep Helper to avoid refactoring
| 
           The impact of refactoring to allow constructor or method injection of  
 Introducing a dependency through all these layers would necessitate registering these components with the DI container. This represents a fundamental architectural shift that is beyond the scope of this current work. Therefore, I will retain the  为了允许通过构造函数或方法注入  
 将依赖项引入所有这些层需要将这些组件注册到 DI 容器中。这代表了一种架构性改变,超出了当前工作的范围。 因此,我将保留  https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.time.testing.faketimeprovider  | 
    
| 
           不用注入,我用词不当,现阶段只要通过参数传入就可以了  | 
    
| 
           Understood, you meant simply passing the parameter down. My point was that this is also cumbersome as it requires changing many layers. This may have been lost in the AI translation. For now, should I proceed with passing the parameter? 明白了,您是指简单地将参数传递下去。 我的观点是这也很麻烦,因为需要修改很多层。这一点可能在 AI 翻译中被遗漏了。 目前,我是否应该先进行参数传递的重构?  | 
    
          
 这个从方法传入参数的似乎是最简单的,injection翻译成注入确实没错,但在大杂烩的代码中实施严格的DI太难了,所以往往就降级成简单的参数传递了 ╮(╯▽╰)╭ 具体还是你操刀哈,我也只是来围观的  | 
    
          
 Ah, I realized I didn't provide context about the static helper function. It's just a simple wrapper with a method to get DateTimeOffset directly to avoid repeating code. The most important part is accessing the Config, which appears to be already available everywhere through the global  啊,我意识到我没有说明这个静态辅助函数的上下文。它只是一个简单的包装器,提供了一个直接获取 DateTimeOffset 的方法,以避免代码重复。最关键的部分是访问 Config(配置),这似乎已经可以通过全局的   | 
    
…on to use server time or local time, refactor GetExecutionOrder
…roupProject->TaskCompletionSkipRuleConfig->BoundaryHour add option to use server time or local time, refactor IsSkipTask->IsTodayByBoundary and ScriptGroupProject.Run
| 
           While refactoring  In the method  Inside the method  The methods in  Some assumptions were made in this commit. If it causes unwanted behavior, it can be reverted. 在重构  在  在  
 这个提交中做出了一些假设。如果导致不希望的行为,可以将其还原。  | 
    
…field lost for some reason
| 
           The PR is now complete. I found no more candidate operations requiring server time refactoring. Summary: 
 PR 现已完成。未发现更多需要重构的服务器时间相关操作。 总结: 
  | 
    





english
Refactor Server Reset Time Handling
Refactor Tasks to Use Configurable UTC Server Reset Time
This pull request refactors several game-related tasks to use a new, configurable
ServerResetTimestruct. The goal is to eliminate hard-coded server reset logic, making the application more flexible and robust.Previously, the application's logic assumed a fixed reset time based on the China/Asia/SAR server (Monday, 4 AM GMT+8). This approach is unreliable because it:
The new
ServerResetTimestruct addresses these issues by:IsWeeklyResetHourandGetDayOfWeekthat handle all the necessary date and time calculations. This ensures that the application's logic consistently reflects the correct server time, regardless of the user's location.Changes
BetterGenshinImpact/Model/ServerResetTime.cs: A new struct to encapsulate a server's weekly reset day and hour in UTC.BetterGenshinImpact/Core/Config/OtherConfig.cs: A new setting for a custom server reset time has been added.BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs: Provides default server options (CN/Asia/SAR, EU, NA) for the user to choose from.BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml: A new configuration component is added to the GUI, allowing users to select a preset or type a custom reset time.BetterGenshinImpact/View/Converters/StringToServerResetTimeConverter.cs&BetterGenshinImpact/App.xaml: A converter is registered to handle string-to-ServerResetTimeconversions for user input.ServerResetTimeobject's methods instead of hard-coded date logic:BetterGenshinImpact/GameTask/Common/Job/BlessingOfTheWelkinMoonTask.csBetterGenshinImpact/GameTask/Common/Job/GoToSereniteaPotTask.csBetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.csBetterGenshinImpact/Core/Config/OneDragonFlowConfig.csTest/BetterGenshinImpact.UnitTest/ServerResetTimeTest.cs, has been added to ensure the new date logic is correct. This file can be removed after the review.Notes
Asking for Review
ServerResetTime.csfile should be placed. I've temporarily added it to theModelfolder. Please advise on the correct location..Houror.Nowin the IDE.TaskContext.Instance().Config.OtherConfig. As I'm not familiar with the project's dependency management strategy, I'm unsure if this is the intended way to retrieve the configuration in different parts of the application.Chinese AI translation:
重构任务以使用可配置的UTC服务器重置时间
本次拉取请求重构了几个游戏相关任务,以使用一个新的可配置的
ServerResetTime结构体。目的是消除硬编码的服务器重置逻辑,使应用程序更加灵活和健壮。以前,应用程序的逻辑依赖于中/亚/SAR服的固定重置时间(GMT+8时间周一凌晨4点)。这种方法不可靠,因为它:
新的
ServerResetTime结构体通过以下方式解决了这些问题:IsWeeklyResetHour和GetDayOfWeek等辅助方法,处理所有必要的日期和时间计算。这确保了无论用户身处何地,应用程序的逻辑都能始终反映正确的服务器时间。更改内容
BetterGenshinImpact/Model/ServerResetTime.cs: 一个新的结构体,用于封装服务器的每周重置日期和小时(UTC)。BetterGenshinImpact/Core/Config/OtherConfig.cs: 添加了一个用于配置自定义服务器重置时间的新设置。BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs: 为用户提供了默认的服务器选项(中/亚/SAR服、欧服、美服)。BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml: 在图形用户界面中添加了一个新的配置组件,允许用户选择预设选项或输入自定义重置时间。BetterGenshinImpact/View/Converters/StringToServerResetTimeConverter.cs&BetterGenshinImpact/App.xaml: 注册了一个转换器,用于处理字符串到ServerResetTime类型的转换,以支持用户输入。ServerResetTime对象方法,而非硬编码的日期逻辑:BetterGenshinImpact/GameTask/Common/Job/BlessingOfTheWelkinMoonTask.csBetterGenshinImpact/GameTask/Common/Job/GoToSereniteaPotTask.csBetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.csBetterGenshinImpact/Core/Config/OneDragonFlowConfig.csTest/BetterGenshinImpact.UnitTest/ServerResetTimeTest.cs,以确保新的日期逻辑正确无误。该文件可以在审查后删除。注意事项
征求审查意见
ServerResetTime.cs文件应放在哪里。目前我暂时将其放在了Model文件夹下。请告知正确的存放位置。.Hour或.Now来找到它们。TaskContext.Instance().Config.OtherConfig来访问配置对象。由于我不熟悉该项目的依赖管理策略,不确定这是在应用程序中获取配置的预期方式。