C#/.NET Future Relative Timestamps?
I'm looking for some way to make a relative text timestamp but using future instead of past (not "2 days ago" but "in 2 days").
I'm making a personal task manager for my personal usages and I'd like it to tell me "this task is due in 2 days". But I can't seem to find nothing to convert a DateTime
to that kind of timestamp开发者_如何学运维.
This doesn't work for you?...
DateTime myTask = DateTime.Now.AddDays(2.0);
Update
As Reed pointed out in the comment box below, the OP might also be looking for a way to tell the time until the task is due or the time the task has been past due. I think something like this will work (note that I have not compiled this code, but it should give you a good idea):
public string PrintTaskDueTime(DateTime taskTime, DateTime currTime)
{
string result = string.Empty;
TimeSpan timeDiff = TimeSpan.Zero;
if(taskTime > currTime)
{
timeDiff = taskTime-currTime;
result = String.Format("Your task is due in {0} days and {1} hours.", timeDiff.TotalDays, timeDiff.Hours);
}
else if(taskTime == currTime)
{
result = "Your task is due now!";
}
else
{
timeDiff = currTime-taskTime;
result = String.Format("Your task is {0} days and {1} hours past due!", timeDiff.TotalDays, timeDiff.Hours);
}
return result;
}
So just call it by specifying the task time and the current time: PrintTimeDiff(taskTime, DateTime.Now);
I hope that helps.
If you have the date that it's due in a DateTime
, then you can use a TimeSpan
to get the time until due. For example:
TimeSpan dueDuration = dueDate - DateTime.Now;
Console.WriteLine("Due in {0} days and {1} hours.", dueDuration.TotalDays, dueDurations.Hours);
The DateTime type is used to represent specific points in time. For example, DateTime.Now.
The TimeSpan is used to represent specific durations of time. For example, TimeSpan.FromDays(2).
There are operator overloads that allow them to interact nicely with one another, For example,
DateTime dueDate = DateTime.Now + TimeSpan.FromDays(2);
A future relative timestamp is just like a past, but with the sign different.
string RelativeTime(DateTime when)
{
TimeSpan diff = when - DateTime.Now;
var minutes = (int) diff.TotalMinutes;
if (minutes == 1)
return "A minute from now";
if (minute == 2)
return "In a couple minutes";
if (minutes < 10)
return "In not 10 minutes";
if (minutes < 40)
return "In about half an hour";
/* etc */
}
The / * etc * / part is tedious and requires creativity, but that's up to you.
Based on all the replies I finally made one myself which meets all my requierements:
public static string RemainingTimeBeforeDateTime(DateTime dateTime, int level = 1)
{
int howDeep = 0;
string result = "";
TimeSpan dueDuration = dateTime - DateTime.Now;
double days = dueDuration.Days;
double hours = dueDuration.Hours;
double minutes = dueDuration.Minutes;
if (days > 0)
{
howDeep++;
result = days + "d ";
}
if (((howDeep != level) && (days != 0)) || ((days == 0) && (hours > 0)))
{
howDeep++;
result = result + hours + "h ";
}
if (((howDeep != level) && (hours != 0)) || ((hours == 0) && (minutes > 0)))
{
result = result + minutes + "m ";
}
return result;
}
Here's something I put together based on James' answer. Supports past, present, and future :)
Note: It can probably be shortened a bit more.
public static string RelativeTime(DateTime Date, string NowText = "Now")
{
const int SECOND = 1;
const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;
TimeSpan TimeSpan;
double delta = 0d;
//It's in the future
if (Date > DateTime.UtcNow)
{
TimeSpan = new TimeSpan(Date.Ticks - DateTime.UtcNow.Ticks);
delta = Math.Abs(TimeSpan.TotalSeconds);
if (delta < 1 * MINUTE)
{
if (TimeSpan.Seconds == 0)
return NowText;
else
return TimeSpan.Seconds == 1 ? "A second from now" : TimeSpan.Seconds + " seconds from now";
}
if (delta < 2 * MINUTE)
return "A minute from now";
if (delta < 45 * MINUTE)
return TimeSpan.Minutes + " minutes from now";
if (delta < 90 * MINUTE)
return "An hour from now";
if (delta < 24 * HOUR)
return TimeSpan.Hours + " hours from now";
if (delta < 48 * HOUR)
return "Tomorrow";
if (delta < 30 * DAY)
return TimeSpan.Days + " days from now";
if (delta < 12 * MONTH)
{
int months = Convert.ToInt32(Math.Floor((double)TimeSpan.Days / 30));
return months <= 1 ? "A month from now" : months + " months from now";
}
else
{
int years = Convert.ToInt32(Math.Floor((double)TimeSpan.Days / 365));
return years <= 1 ? "A year from now" : years + " years from now";
}
}
//It's in the past
else if (Date < DateTime.UtcNow)
{
TimeSpan = new TimeSpan(DateTime.UtcNow.Ticks - Date.Ticks);
delta = Math.Abs(TimeSpan.TotalSeconds);
if (delta < 1 * MINUTE)
{
if (TimeSpan.Seconds == 0)
return NowText;
else
return TimeSpan.Seconds == 1 ? "A second ago" : TimeSpan.Seconds + " seconds ago";
}
if (delta < 2 * MINUTE)
return "A minute ago";
if (delta < 45 * MINUTE)
return TimeSpan.Minutes + " minutes ago";
if (delta < 90 * MINUTE)
return "An hour ago";
if (delta < 24 * HOUR)
return TimeSpan.Hours + " hours ago";
if (delta < 48 * HOUR)
return "Yesterday";
if (delta < 30 * DAY)
return TimeSpan.Days + " days ago";
if (delta < 12 * MONTH)
{
int months = Convert.ToInt32(Math.Floor((double)TimeSpan.Days / 30));
return months <= 1 ? "A month ago" : months + " months ago";
}
else
{
int years = Convert.ToInt32(Math.Floor((double)TimeSpan.Days / 365));
return years <= 1 ? "A year ago" : years + " years ago";
}
}
//It's now
else
return NowText;
}
精彩评论