使用 Discord 机器人进行 C# 时间减法
C# Time Subtraction With a Discord Bot
我正在制作一个有趣的 discord 机器人,它可以在时钟上找到下一个 4:20,无论是上午还是下午,并告诉您还有多长时间 4:20。我的代码在 4:20 之前的一个小时之前都可以正常工作,然后它会跳过并告诉下一个 4:20 之前还有多长时间,而不是显示“0 小时 59 分钟”。我在想我格式化时间输出的方式可能存在问题,但我对 C# 很陌生,不知道如何修复它。我已经包含了我的代码以及当前输出的屏幕截图。在屏幕截图中,机器人也有一分钟的时间,但从那时起我就想出了如何解决这个问题。我知道代码不是最有效或最干净的,但我还是编程新手。
//Finds next 4:20 on the clock
[Command("420")]
public async Task WeedMinute()
{
DateTime currentTime = DateTime.Now; //Current time
DateTime weedMinuteMorning = Convert.ToDateTime("4:21:00"); //4:20am
DateTime weedMinuteEvening = Convert.ToDateTime("16:21:00"); //4:20pm
string weedMinutePM = "16:21:00"; //These variables are used in subtraction
string weedMinuteAM = "4:21:00";
if (currentTime <= weedMinuteEvening)
{
//chooseMorningEvening is the output time string
DateTime chooseMorningEvening = (DateTime.Parse(weedMinutePM).Subtract(currentTime.TimeOfDay));
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + chooseMorningEvening.ToString(@"hh") + " hours " + chooseMorningEvening.ToString(@"mm") + " minutes.");
}
else if (currentTime >= weedMinuteMorning)
{
//chooseMorningEvening is the output time string
DateTime chooseMorningEvening = (DateTime.Parse(weedMinuteAM).Subtract(currentTime.TimeOfDay));
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + chooseMorningEvening.ToString(@"hh") + " hours " + chooseMorningEvening.ToString(@"mm") + " minutes.");
}
}
这里有一个DateTime.Compare函数可以用来修复下面的错误
//DateTime currentTime = DateTime.Now; //Current time
DateTime currentTime = Convert.ToDateTime("3:22:00"); // An example time for 0 hours and 59 mins
DateTime weedMinuteMorning = Convert.ToDateTime("4:21:00"); //4:20am
DateTime weedMinuteEvening = Convert.ToDateTime("16:21:00"); //4:20pm
string weedMinutePM = "16:21:00"; //These variables are used in subtraction
string weedMinuteAM = "4:21:00";
if(currentTime.CompareTo(weedMinuteMorning) < 1) //less than or same as Morning 4:20 am
{
var chooseMorningEvening = weedMinuteMorning - currentTime;
string m = "The next weed minute will happen in " + chooseMorningEvening.Hours + " hours " + chooseMorningEvening.Minutes + " minutes.";
}
else
{
var chooseMorningEvening = weedMinuteEvening - currentTime;
string m = "The next weed minute will happen in " + chooseMorningEvening.Hours + " hours " + chooseMorningEvening.Minutes + " minutes.";
}
您的时间输出格式看起来还不错,只是为了更好的格式,请参阅 Custom TimeSpan format strings.
您的代码存在三个问题:
1.如果条件
if (currentTime <= weedMinuteEvening)
{
//this condition is true from 00:00:00 to 16:21:01 so for dates less than 4:21:00
//you get incorrect output, and next condition execute just for dates greater than 16:21:00.
...
}
else if (currentTime >= weedMinuteMorning)
{
//This code execute only for dates greater than 16:21:00.
...
}
正如 Adam 建议的那样,您必须从 currentTime
中删除 .TimeOfDay
,但这还不够。
您必须处理大于 16:21:00
的日期
所以我希望这段代码对你有用:
[Command("420")]
public async Task WeedMinute()
{
DateTime currentTime = DateTime.Now; //Current time
DateTime weedMinuteMorning = Convert.ToDateTime("4:21:00"); //4:20am
DateTime weedMinuteEvening = Convert.ToDateTime("16:21:00"); //4:20pm
//I removed These variables, Don't need to parse same DateTime again. change it as you wish
//string weedMinutePM = "16:21:00";
//string weedMinuteAM = "4:21:00";
if (currentTime <= weedMinuteMorning)
{
TimeSpan timeSpan = weedMinuteMorning.Subtract(currentTime);
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + timeSpan.ToString("hh' hours 'mm' minutes.'"));
}
else if (currentTime <= weedMinuteEvening)
{
TimeSpan timeSpan = weedMinuteEvening.Subtract(currentTime);
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + timeSpan.ToString("hh' hours 'mm' minutes.'"));
}
else
{
//To handle dates greater than 16:21:00, we must calculate hours
//remaining until 4:20 next day.
weedMinuteMorning = weedMinuteMorning.AddDays(1);
TimeSpan timeSpan = weedMinuteMorning.Subtract(currentTime);
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + timeSpan.ToString("hh' hours 'mm' minutes.'"));
}
}
你的代码的问题在于它没有处理所有可能发生的情况(共有三种):
- 时间在 00:00:00 和 04:20:00 之间 => 计算到 04:20:00
的时间
- 时间在 04:20:00 和 16:20:00 之间 => 计算到 16:20:00
的时间
- 时间在 16:20:00 之后 => 计算时间到 04:20:00,第二天。
如果您观察到下一次抽烟的时间应始终在 0 到 12 小时之间,则可以稍微简化一下。所以,如果你只计算 16:20 之前的时间,如果它大于 12 小时,那么你必须在 04:20 之前起床,你可以减去 12 小时。如果时间小于 0(即负数),那么你必须晚于 16:20 所以你只需添加 12 小时。在代码中,它看起来像这样:
public static TimeSpan CalculateTimeToWeed(DateTime from)
{
DateTime weedTime = Convert.ToDateTime("16:20:00");
TimeSpan twelveHours = TimeSpan.FromHours(12.0);
TimeSpan timeToWeed = weedTime - from;
double totalHours = timeToWeed.TotalHours;
if (totalHours > 12.0)
{
timeToWeed -= twelveHours;
}
else if (totalHours < 0.0)
{
timeToWeed += twelveHours;
}
return timeToWeed;
}
您可以将其集成到您的 Discord 机器人中,如下所示:
[Command("420")]
public async Task WeedMinute()
{
DateTime currentTime = DateTime.Now;
TimeSpan timeToWeed = CalculateTimeToWeed(currentTime);
string message = "The next weed minute will happen in " + timeToWeed.ToString("hh' hours 'mm' minutes.'");
await Context.Channel.SendMessageAsync(message);
}
您可以减少其中的行数,但是使用这些临时变量可以让事情更容易调试。您可以在使用调试器单步执行时检查 currentTime
是否符合您的预期,timeToWeed
是否合理等等。
将代码分成两个函数也有很多优点:
- 您可以测试独立于机器人的时间计算
- 代码更清晰,你没有把通信代码和计算代码搞混了。
希望这对您有所帮助。
我正在制作一个有趣的 discord 机器人,它可以在时钟上找到下一个 4:20,无论是上午还是下午,并告诉您还有多长时间 4:20。我的代码在 4:20 之前的一个小时之前都可以正常工作,然后它会跳过并告诉下一个 4:20 之前还有多长时间,而不是显示“0 小时 59 分钟”。我在想我格式化时间输出的方式可能存在问题,但我对 C# 很陌生,不知道如何修复它。我已经包含了我的代码以及当前输出的屏幕截图。在屏幕截图中,机器人也有一分钟的时间,但从那时起我就想出了如何解决这个问题。我知道代码不是最有效或最干净的,但我还是编程新手。
//Finds next 4:20 on the clock
[Command("420")]
public async Task WeedMinute()
{
DateTime currentTime = DateTime.Now; //Current time
DateTime weedMinuteMorning = Convert.ToDateTime("4:21:00"); //4:20am
DateTime weedMinuteEvening = Convert.ToDateTime("16:21:00"); //4:20pm
string weedMinutePM = "16:21:00"; //These variables are used in subtraction
string weedMinuteAM = "4:21:00";
if (currentTime <= weedMinuteEvening)
{
//chooseMorningEvening is the output time string
DateTime chooseMorningEvening = (DateTime.Parse(weedMinutePM).Subtract(currentTime.TimeOfDay));
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + chooseMorningEvening.ToString(@"hh") + " hours " + chooseMorningEvening.ToString(@"mm") + " minutes.");
}
else if (currentTime >= weedMinuteMorning)
{
//chooseMorningEvening is the output time string
DateTime chooseMorningEvening = (DateTime.Parse(weedMinuteAM).Subtract(currentTime.TimeOfDay));
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + chooseMorningEvening.ToString(@"hh") + " hours " + chooseMorningEvening.ToString(@"mm") + " minutes.");
}
}
这里有一个DateTime.Compare函数可以用来修复下面的错误
//DateTime currentTime = DateTime.Now; //Current time
DateTime currentTime = Convert.ToDateTime("3:22:00"); // An example time for 0 hours and 59 mins
DateTime weedMinuteMorning = Convert.ToDateTime("4:21:00"); //4:20am
DateTime weedMinuteEvening = Convert.ToDateTime("16:21:00"); //4:20pm
string weedMinutePM = "16:21:00"; //These variables are used in subtraction
string weedMinuteAM = "4:21:00";
if(currentTime.CompareTo(weedMinuteMorning) < 1) //less than or same as Morning 4:20 am
{
var chooseMorningEvening = weedMinuteMorning - currentTime;
string m = "The next weed minute will happen in " + chooseMorningEvening.Hours + " hours " + chooseMorningEvening.Minutes + " minutes.";
}
else
{
var chooseMorningEvening = weedMinuteEvening - currentTime;
string m = "The next weed minute will happen in " + chooseMorningEvening.Hours + " hours " + chooseMorningEvening.Minutes + " minutes.";
}
您的时间输出格式看起来还不错,只是为了更好的格式,请参阅 Custom TimeSpan format strings.
您的代码存在三个问题:
1.如果条件
if (currentTime <= weedMinuteEvening)
{
//this condition is true from 00:00:00 to 16:21:01 so for dates less than 4:21:00
//you get incorrect output, and next condition execute just for dates greater than 16:21:00.
...
}
else if (currentTime >= weedMinuteMorning)
{
//This code execute only for dates greater than 16:21:00.
...
}
正如 Adam 建议的那样,您必须从
currentTime
中删除.TimeOfDay
,但这还不够。您必须处理大于 16:21:00
的日期
所以我希望这段代码对你有用:
[Command("420")]
public async Task WeedMinute()
{
DateTime currentTime = DateTime.Now; //Current time
DateTime weedMinuteMorning = Convert.ToDateTime("4:21:00"); //4:20am
DateTime weedMinuteEvening = Convert.ToDateTime("16:21:00"); //4:20pm
//I removed These variables, Don't need to parse same DateTime again. change it as you wish
//string weedMinutePM = "16:21:00";
//string weedMinuteAM = "4:21:00";
if (currentTime <= weedMinuteMorning)
{
TimeSpan timeSpan = weedMinuteMorning.Subtract(currentTime);
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + timeSpan.ToString("hh' hours 'mm' minutes.'"));
}
else if (currentTime <= weedMinuteEvening)
{
TimeSpan timeSpan = weedMinuteEvening.Subtract(currentTime);
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + timeSpan.ToString("hh' hours 'mm' minutes.'"));
}
else
{
//To handle dates greater than 16:21:00, we must calculate hours
//remaining until 4:20 next day.
weedMinuteMorning = weedMinuteMorning.AddDays(1);
TimeSpan timeSpan = weedMinuteMorning.Subtract(currentTime);
await Context.Channel.SendMessageAsync("The next weed minute will happen in " + timeSpan.ToString("hh' hours 'mm' minutes.'"));
}
}
你的代码的问题在于它没有处理所有可能发生的情况(共有三种):
- 时间在 00:00:00 和 04:20:00 之间 => 计算到 04:20:00 的时间
- 时间在 04:20:00 和 16:20:00 之间 => 计算到 16:20:00 的时间
- 时间在 16:20:00 之后 => 计算时间到 04:20:00,第二天。
如果您观察到下一次抽烟的时间应始终在 0 到 12 小时之间,则可以稍微简化一下。所以,如果你只计算 16:20 之前的时间,如果它大于 12 小时,那么你必须在 04:20 之前起床,你可以减去 12 小时。如果时间小于 0(即负数),那么你必须晚于 16:20 所以你只需添加 12 小时。在代码中,它看起来像这样:
public static TimeSpan CalculateTimeToWeed(DateTime from)
{
DateTime weedTime = Convert.ToDateTime("16:20:00");
TimeSpan twelveHours = TimeSpan.FromHours(12.0);
TimeSpan timeToWeed = weedTime - from;
double totalHours = timeToWeed.TotalHours;
if (totalHours > 12.0)
{
timeToWeed -= twelveHours;
}
else if (totalHours < 0.0)
{
timeToWeed += twelveHours;
}
return timeToWeed;
}
您可以将其集成到您的 Discord 机器人中,如下所示:
[Command("420")]
public async Task WeedMinute()
{
DateTime currentTime = DateTime.Now;
TimeSpan timeToWeed = CalculateTimeToWeed(currentTime);
string message = "The next weed minute will happen in " + timeToWeed.ToString("hh' hours 'mm' minutes.'");
await Context.Channel.SendMessageAsync(message);
}
您可以减少其中的行数,但是使用这些临时变量可以让事情更容易调试。您可以在使用调试器单步执行时检查 currentTime
是否符合您的预期,timeToWeed
是否合理等等。
将代码分成两个函数也有很多优点:
- 您可以测试独立于机器人的时间计算
- 代码更清晰,你没有把通信代码和计算代码搞混了。
希望这对您有所帮助。