“Pretty” date generatorGet remaining days in date rangeDate ranges from a given start dateDate Comparison...
Align centered, ragged right and ragged left in align environment
Asserting that Atheism and Theism are both faith based positions
Print a physical multiplication table
When did hardware antialiasing start being available?
What kind of footwear is suitable for walking in micro gravity environment?
label a part of commutative diagram
Unfrosted light bulb
Does convergence of polynomials imply that of its coefficients?
Splitting fasta file into smaller files based on header pattern
How do you balance your desire for liberation with your wordly desires?
How to find the largest number(s) in a list of elements?
How can I get files using find command
Why is participating in the European Parliamentary elections used as a threat?
Nested Dynamic SOQL Query
When should a starting writer get his own webpage?
How can an organ that provides biological immortality be unable to regenerate?
What (if any) is the reason to buy in small local stores?
Right piano pedal is bright
Bandwidth limit Cisco 3400 ME problem
Why didn’t Eve recognize the little cockroach as a living organism?
TDE Master Key Rotation
If I cast enlarge/reduce on an arrow, what weapon could it count as?
Someone scrambled my calling sign- who am I?
Why are there no stars visible in cislunar space?
“Pretty” date generator
Get remaining days in date rangeDate ranges from a given start dateDate Comparison ScriptDate Range TreeDifferent date formatsWeb API Interview Practical TestImplementing a week schedule class in C#Date only limited function classPython library for calculating next and previous time of the cron-like scheduled task
$begingroup$
I have this "pretty" date string generator in C# - pass it a date and it returns a string with "5 minutes ago" or "2 weeks, 3 days ago", etc.
It's a little verbose and hogs 61 lines, and I'm wondering if I'm missing out on some nice C# features or something. What (if any) is the best way to clean up this code? Are there any cool c# features I can use here?
public static string getTimeSpan(DateTime postDate)
{
string stringy = "";
TimeSpan diff = DateTime.Now.Subtract(postDate);
double years = Math.Floor(diff.TotalDays / 365);
double weeks = Math.Floor(diff.TotalDays / 7);
double days = diff.Days;
double hours = diff.Hours + days * 24;
double minutes = diff.Minutes + hours * 60;
if (minutes <= 1) {
stringy = "Just Now";
} else if (years >= 1) {
if (years >= 2) {
stringy = years.ToString() + " years ago";
} else {
stringy = "1 year ago";
}
} else if (weeks >= 1) {
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
} else if (days >= 1) {
if ((hours - days * 24) > 0) {
if ((hours - days * 24) > 1) {
stringy = ", " + (hours - days * 24).ToString() + " hours";
} else {
stringy = ", " + (hours - days * 24).ToString() + " hour";
}
}
if (days >= 2) {
stringy = days.ToString() + " days" + stringy + " ago";
} else {
stringy = "1 day" + stringy + " ago";
}
} else if (hours >= 1) {
if ((minutes - hours * 60) > 0) {
if ((minutes - hours * 60) > 1) {
stringy = ", " + (minutes - hours * 60).ToString() + " minutes";
} else {
stringy = ", " + (minutes - hours * 60).ToString() + " minute";
}
}
if (hours >= 2) {
stringy = hours.ToString() + " hours" + stringy + " ago";
} else {
stringy = "1 hour" + stringy + " ago";
}
} else if (minutes > 1) {
stringy = minutes.ToString() + " minutes ago";
}
return stringy;
}
c# datetime
$endgroup$
add a comment |
$begingroup$
I have this "pretty" date string generator in C# - pass it a date and it returns a string with "5 minutes ago" or "2 weeks, 3 days ago", etc.
It's a little verbose and hogs 61 lines, and I'm wondering if I'm missing out on some nice C# features or something. What (if any) is the best way to clean up this code? Are there any cool c# features I can use here?
public static string getTimeSpan(DateTime postDate)
{
string stringy = "";
TimeSpan diff = DateTime.Now.Subtract(postDate);
double years = Math.Floor(diff.TotalDays / 365);
double weeks = Math.Floor(diff.TotalDays / 7);
double days = diff.Days;
double hours = diff.Hours + days * 24;
double minutes = diff.Minutes + hours * 60;
if (minutes <= 1) {
stringy = "Just Now";
} else if (years >= 1) {
if (years >= 2) {
stringy = years.ToString() + " years ago";
} else {
stringy = "1 year ago";
}
} else if (weeks >= 1) {
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
} else if (days >= 1) {
if ((hours - days * 24) > 0) {
if ((hours - days * 24) > 1) {
stringy = ", " + (hours - days * 24).ToString() + " hours";
} else {
stringy = ", " + (hours - days * 24).ToString() + " hour";
}
}
if (days >= 2) {
stringy = days.ToString() + " days" + stringy + " ago";
} else {
stringy = "1 day" + stringy + " ago";
}
} else if (hours >= 1) {
if ((minutes - hours * 60) > 0) {
if ((minutes - hours * 60) > 1) {
stringy = ", " + (minutes - hours * 60).ToString() + " minutes";
} else {
stringy = ", " + (minutes - hours * 60).ToString() + " minute";
}
}
if (hours >= 2) {
stringy = hours.ToString() + " hours" + stringy + " ago";
} else {
stringy = "1 hour" + stringy + " ago";
}
} else if (minutes > 1) {
stringy = minutes.ToString() + " minutes ago";
}
return stringy;
}
c# datetime
$endgroup$
add a comment |
$begingroup$
I have this "pretty" date string generator in C# - pass it a date and it returns a string with "5 minutes ago" or "2 weeks, 3 days ago", etc.
It's a little verbose and hogs 61 lines, and I'm wondering if I'm missing out on some nice C# features or something. What (if any) is the best way to clean up this code? Are there any cool c# features I can use here?
public static string getTimeSpan(DateTime postDate)
{
string stringy = "";
TimeSpan diff = DateTime.Now.Subtract(postDate);
double years = Math.Floor(diff.TotalDays / 365);
double weeks = Math.Floor(diff.TotalDays / 7);
double days = diff.Days;
double hours = diff.Hours + days * 24;
double minutes = diff.Minutes + hours * 60;
if (minutes <= 1) {
stringy = "Just Now";
} else if (years >= 1) {
if (years >= 2) {
stringy = years.ToString() + " years ago";
} else {
stringy = "1 year ago";
}
} else if (weeks >= 1) {
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
} else if (days >= 1) {
if ((hours - days * 24) > 0) {
if ((hours - days * 24) > 1) {
stringy = ", " + (hours - days * 24).ToString() + " hours";
} else {
stringy = ", " + (hours - days * 24).ToString() + " hour";
}
}
if (days >= 2) {
stringy = days.ToString() + " days" + stringy + " ago";
} else {
stringy = "1 day" + stringy + " ago";
}
} else if (hours >= 1) {
if ((minutes - hours * 60) > 0) {
if ((minutes - hours * 60) > 1) {
stringy = ", " + (minutes - hours * 60).ToString() + " minutes";
} else {
stringy = ", " + (minutes - hours * 60).ToString() + " minute";
}
}
if (hours >= 2) {
stringy = hours.ToString() + " hours" + stringy + " ago";
} else {
stringy = "1 hour" + stringy + " ago";
}
} else if (minutes > 1) {
stringy = minutes.ToString() + " minutes ago";
}
return stringy;
}
c# datetime
$endgroup$
I have this "pretty" date string generator in C# - pass it a date and it returns a string with "5 minutes ago" or "2 weeks, 3 days ago", etc.
It's a little verbose and hogs 61 lines, and I'm wondering if I'm missing out on some nice C# features or something. What (if any) is the best way to clean up this code? Are there any cool c# features I can use here?
public static string getTimeSpan(DateTime postDate)
{
string stringy = "";
TimeSpan diff = DateTime.Now.Subtract(postDate);
double years = Math.Floor(diff.TotalDays / 365);
double weeks = Math.Floor(diff.TotalDays / 7);
double days = diff.Days;
double hours = diff.Hours + days * 24;
double minutes = diff.Minutes + hours * 60;
if (minutes <= 1) {
stringy = "Just Now";
} else if (years >= 1) {
if (years >= 2) {
stringy = years.ToString() + " years ago";
} else {
stringy = "1 year ago";
}
} else if (weeks >= 1) {
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
} else if (days >= 1) {
if ((hours - days * 24) > 0) {
if ((hours - days * 24) > 1) {
stringy = ", " + (hours - days * 24).ToString() + " hours";
} else {
stringy = ", " + (hours - days * 24).ToString() + " hour";
}
}
if (days >= 2) {
stringy = days.ToString() + " days" + stringy + " ago";
} else {
stringy = "1 day" + stringy + " ago";
}
} else if (hours >= 1) {
if ((minutes - hours * 60) > 0) {
if ((minutes - hours * 60) > 1) {
stringy = ", " + (minutes - hours * 60).ToString() + " minutes";
} else {
stringy = ", " + (minutes - hours * 60).ToString() + " minute";
}
}
if (hours >= 2) {
stringy = hours.ToString() + " hours" + stringy + " ago";
} else {
stringy = "1 hour" + stringy + " ago";
}
} else if (minutes > 1) {
stringy = minutes.ToString() + " minutes ago";
}
return stringy;
}
c# datetime
c# datetime
edited Mar 6 '15 at 13:30
Jamal♦
30.4k11121227
30.4k11121227
asked May 31 '11 at 16:51
Thomas ShieldsThomas Shields
243313
243313
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
$begingroup$
- Use PascalCase for the method name
- Move the calc for years and months lower to be minutely "more efficient"
- Use inline
return
to reduces nesting - Use ternary operator (
?:
) for simple logic to reduceif/else
clutter - Use the
format
override ofToString(string format)
to reduce string concats - Use
string.Format
with a ternary to reduce duplication
The shorter version I came up with is 40 lines, but you can judge if it readable enough.
public static string GetTimeSpan(DateTime postDate) {
string stringy = string.Empty;
TimeSpan diff = DateTime.Now.Subtract(postDate);
double days = diff.Days;
double hours = diff.Hours + days*24;
double minutes = diff.Minutes + hours*60;
if (minutes <= 1) {
return "Just Now";
}
double years = Math.Floor(diff.TotalDays/365);
if (years >= 1) {
return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
}
double weeks = Math.Floor(diff.TotalDays/7);
if (weeks >= 1) {
double partOfWeek = days - weeks*7;
if (partOfWeek > 0) {
stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
}
return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
}
if (days >= 1) {
double partOfDay = hours - days*24;
if (partOfDay > 0) {
stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
}
return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
}
if (hours >= 1) {
double partOfHour = minutes - hours*60;
if (partOfHour > 0) {
stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
}
return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
}
// Only condition left is minutes > 1
return minutes.ToString("# minutes ago");
}
$endgroup$
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
It is important to remove lastreturn
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which isstring.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
1
$begingroup$
The last line should bereturn string.Format("{0} minutes ago", minutes);
asminutes.ToString("{0} minutes ago")
will return{xxx} minutes ago
.
$endgroup$
– mono blaine
Mar 13 at 14:41
1
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead ofstring.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
|
show 2 more comments
$begingroup$
Some things are repeated:
days - weeks * 7
hours - days * 24
minutes - hours * 60
These can and should be made into their own variables - but what you are really after seems to be
days % 7
hours % 24
minutes % 60
You can replace:
double hours = diff.Hours + days * 24;
with
double hours = diff.TotalHours;
There is also a TotalMinutes. You can just use the Math.Floor() of these values to get an int.
I see that you are going for a single exit point for this function, but I think that readability would be improved if you got some of the simpler paths shorter:
if (minutes <= 1)
return "Just Now";
if (years >= 1) {
if (years >= 2) {
return years.ToString() + " years ago";
} else {
return "1 year ago";
}
EDIT to add:
There's a repeated block of code that could be refactored to its own function:
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
The body of the extracted function would look like:
if (smallUnitCount > 0) {
if (smallUnitCount > 1) {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitPluralName);
} else {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitSingularName);
}
}
if (largeUnitCount >= 2) {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitPluralName, stringy);
} else {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitSingularName, stringy);
}
$endgroup$
add a comment |
$begingroup$
I would use casting double
to int
instead of Floor
in your case. Firstly because I'm a little bit cautious about equality comparison of doubles in years >= 1
. I would write it in this way:
int years = (int)(diff.TotalDays/365);
$endgroup$
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
1
$begingroup$
Yep, with positive doubles casting toint
doesFloor
exactly. See Explicit conversion section here. It has exactly your sample.
$endgroup$
– Snowbear
May 31 '11 at 21:48
add a comment |
$begingroup$
You can make it an extension, so you can do
string result = DateTime.Now.GetTimeSpan();
Here is how I did it a few time ago
/// <summary>
/// Provide extentions for the DateTime Object.
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// Gets the relative time for a datetime.
/// </summary>
/// <param name="dateTime">The datetime to get the relative time.</param>
/// <returns>A relative time in english.</returns>
public static string GetTimeSpan(this DateTime dateTime)
{
TimeSpan diff = DateTime.Now.Subtract(dateTime);
if (diff.TotalMinutes < 1)
{
return string.Format("{0:D2} second{1} ago", diff.Seconds, PluralizeIfNeeded(diff.Seconds));
}
if (diff.TotalHours < 1)
{
return string.Format("{0:D2} minute{1} ago", diff.Minutes, PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays < 1)
{
return string.Format("{0:D2} hour{2} and {1:D2} minute{3} ago", diff.Hours, diff.Minutes, PluralizeIfNeeded(diff.Hours), PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 2)
{
return string.Format(
"{0:D2} day{3}, {1:D2} hour{4} and {2:D2} minute{5} ago",
diff.Days,
diff.Hours,
diff.Minutes,
PluralizeIfNeeded(diff.Days),
PluralizeIfNeeded(diff.Hours),
PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 30)
{
return string.Format("{0:D2} days ago", diff.TotalDays);
}
return string.Format("{0:g}", dateTime);
}
/// <summary>
/// Gets a 's' if value is > 1.
/// </summary>
/// <param name="testValue">The value to test.</param>
/// <returns>An 's' if value is > 1, otherwise an empty string.</returns>
private static string PluralizeIfNeeded(int testValue)
{
return testValue > 1 ? "s" : string.Empty;
}
}
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f2738%2fpretty-date-generator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
- Use PascalCase for the method name
- Move the calc for years and months lower to be minutely "more efficient"
- Use inline
return
to reduces nesting - Use ternary operator (
?:
) for simple logic to reduceif/else
clutter - Use the
format
override ofToString(string format)
to reduce string concats - Use
string.Format
with a ternary to reduce duplication
The shorter version I came up with is 40 lines, but you can judge if it readable enough.
public static string GetTimeSpan(DateTime postDate) {
string stringy = string.Empty;
TimeSpan diff = DateTime.Now.Subtract(postDate);
double days = diff.Days;
double hours = diff.Hours + days*24;
double minutes = diff.Minutes + hours*60;
if (minutes <= 1) {
return "Just Now";
}
double years = Math.Floor(diff.TotalDays/365);
if (years >= 1) {
return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
}
double weeks = Math.Floor(diff.TotalDays/7);
if (weeks >= 1) {
double partOfWeek = days - weeks*7;
if (partOfWeek > 0) {
stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
}
return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
}
if (days >= 1) {
double partOfDay = hours - days*24;
if (partOfDay > 0) {
stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
}
return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
}
if (hours >= 1) {
double partOfHour = minutes - hours*60;
if (partOfHour > 0) {
stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
}
return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
}
// Only condition left is minutes > 1
return minutes.ToString("# minutes ago");
}
$endgroup$
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
It is important to remove lastreturn
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which isstring.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
1
$begingroup$
The last line should bereturn string.Format("{0} minutes ago", minutes);
asminutes.ToString("{0} minutes ago")
will return{xxx} minutes ago
.
$endgroup$
– mono blaine
Mar 13 at 14:41
1
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead ofstring.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
|
show 2 more comments
$begingroup$
- Use PascalCase for the method name
- Move the calc for years and months lower to be minutely "more efficient"
- Use inline
return
to reduces nesting - Use ternary operator (
?:
) for simple logic to reduceif/else
clutter - Use the
format
override ofToString(string format)
to reduce string concats - Use
string.Format
with a ternary to reduce duplication
The shorter version I came up with is 40 lines, but you can judge if it readable enough.
public static string GetTimeSpan(DateTime postDate) {
string stringy = string.Empty;
TimeSpan diff = DateTime.Now.Subtract(postDate);
double days = diff.Days;
double hours = diff.Hours + days*24;
double minutes = diff.Minutes + hours*60;
if (minutes <= 1) {
return "Just Now";
}
double years = Math.Floor(diff.TotalDays/365);
if (years >= 1) {
return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
}
double weeks = Math.Floor(diff.TotalDays/7);
if (weeks >= 1) {
double partOfWeek = days - weeks*7;
if (partOfWeek > 0) {
stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
}
return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
}
if (days >= 1) {
double partOfDay = hours - days*24;
if (partOfDay > 0) {
stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
}
return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
}
if (hours >= 1) {
double partOfHour = minutes - hours*60;
if (partOfHour > 0) {
stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
}
return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
}
// Only condition left is minutes > 1
return minutes.ToString("# minutes ago");
}
$endgroup$
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
It is important to remove lastreturn
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which isstring.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
1
$begingroup$
The last line should bereturn string.Format("{0} minutes ago", minutes);
asminutes.ToString("{0} minutes ago")
will return{xxx} minutes ago
.
$endgroup$
– mono blaine
Mar 13 at 14:41
1
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead ofstring.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
|
show 2 more comments
$begingroup$
- Use PascalCase for the method name
- Move the calc for years and months lower to be minutely "more efficient"
- Use inline
return
to reduces nesting - Use ternary operator (
?:
) for simple logic to reduceif/else
clutter - Use the
format
override ofToString(string format)
to reduce string concats - Use
string.Format
with a ternary to reduce duplication
The shorter version I came up with is 40 lines, but you can judge if it readable enough.
public static string GetTimeSpan(DateTime postDate) {
string stringy = string.Empty;
TimeSpan diff = DateTime.Now.Subtract(postDate);
double days = diff.Days;
double hours = diff.Hours + days*24;
double minutes = diff.Minutes + hours*60;
if (minutes <= 1) {
return "Just Now";
}
double years = Math.Floor(diff.TotalDays/365);
if (years >= 1) {
return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
}
double weeks = Math.Floor(diff.TotalDays/7);
if (weeks >= 1) {
double partOfWeek = days - weeks*7;
if (partOfWeek > 0) {
stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
}
return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
}
if (days >= 1) {
double partOfDay = hours - days*24;
if (partOfDay > 0) {
stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
}
return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
}
if (hours >= 1) {
double partOfHour = minutes - hours*60;
if (partOfHour > 0) {
stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
}
return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
}
// Only condition left is minutes > 1
return minutes.ToString("# minutes ago");
}
$endgroup$
- Use PascalCase for the method name
- Move the calc for years and months lower to be minutely "more efficient"
- Use inline
return
to reduces nesting - Use ternary operator (
?:
) for simple logic to reduceif/else
clutter - Use the
format
override ofToString(string format)
to reduce string concats - Use
string.Format
with a ternary to reduce duplication
The shorter version I came up with is 40 lines, but you can judge if it readable enough.
public static string GetTimeSpan(DateTime postDate) {
string stringy = string.Empty;
TimeSpan diff = DateTime.Now.Subtract(postDate);
double days = diff.Days;
double hours = diff.Hours + days*24;
double minutes = diff.Minutes + hours*60;
if (minutes <= 1) {
return "Just Now";
}
double years = Math.Floor(diff.TotalDays/365);
if (years >= 1) {
return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
}
double weeks = Math.Floor(diff.TotalDays/7);
if (weeks >= 1) {
double partOfWeek = days - weeks*7;
if (partOfWeek > 0) {
stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
}
return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
}
if (days >= 1) {
double partOfDay = hours - days*24;
if (partOfDay > 0) {
stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
}
return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
}
if (hours >= 1) {
double partOfHour = minutes - hours*60;
if (partOfHour > 0) {
stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
}
return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
}
// Only condition left is minutes > 1
return minutes.ToString("# minutes ago");
}
edited Mar 14 at 16:23
answered May 31 '11 at 20:37
Ed ChapelEd Chapel
31616
31616
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
It is important to remove lastreturn
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which isstring.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
1
$begingroup$
The last line should bereturn string.Format("{0} minutes ago", minutes);
asminutes.ToString("{0} minutes ago")
will return{xxx} minutes ago
.
$endgroup$
– mono blaine
Mar 13 at 14:41
1
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead ofstring.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
|
show 2 more comments
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
It is important to remove lastreturn
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which isstring.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
1
$begingroup$
The last line should bereturn string.Format("{0} minutes ago", minutes);
asminutes.ToString("{0} minutes ago")
will return{xxx} minutes ago
.
$endgroup$
– mono blaine
Mar 13 at 14:41
1
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead ofstring.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
wow thanks! I didn't even know about half these operators and methods and such!
$endgroup$
– Thomas Shields
May 31 '11 at 20:46
$begingroup$
It is important to remove last
return
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which is string.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
It is important to remove last
return
in such cases so compiler will verify that all cases are checked and handled and there is no scenario when this method will return initial value which is string.Empty
$endgroup$
– Snowbear
May 31 '11 at 22:05
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
$begingroup$
Updated the last line to be more explicit with the final return.
$endgroup$
– Ed Chapel
May 31 '11 at 22:30
1
1
$begingroup$
The last line should be
return string.Format("{0} minutes ago", minutes);
as minutes.ToString("{0} minutes ago")
will return {xxx} minutes ago
.$endgroup$
– mono blaine
Mar 13 at 14:41
$begingroup$
The last line should be
return string.Format("{0} minutes ago", minutes);
as minutes.ToString("{0} minutes ago")
will return {xxx} minutes ago
.$endgroup$
– mono blaine
Mar 13 at 14:41
1
1
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead of
string.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
$begingroup$
Can reduce a bit of boilerplate using string interpolation instead of
string.Format
$endgroup$
– Jesse C. Slicer
Mar 14 at 16:29
|
show 2 more comments
$begingroup$
Some things are repeated:
days - weeks * 7
hours - days * 24
minutes - hours * 60
These can and should be made into their own variables - but what you are really after seems to be
days % 7
hours % 24
minutes % 60
You can replace:
double hours = diff.Hours + days * 24;
with
double hours = diff.TotalHours;
There is also a TotalMinutes. You can just use the Math.Floor() of these values to get an int.
I see that you are going for a single exit point for this function, but I think that readability would be improved if you got some of the simpler paths shorter:
if (minutes <= 1)
return "Just Now";
if (years >= 1) {
if (years >= 2) {
return years.ToString() + " years ago";
} else {
return "1 year ago";
}
EDIT to add:
There's a repeated block of code that could be refactored to its own function:
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
The body of the extracted function would look like:
if (smallUnitCount > 0) {
if (smallUnitCount > 1) {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitPluralName);
} else {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitSingularName);
}
}
if (largeUnitCount >= 2) {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitPluralName, stringy);
} else {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitSingularName, stringy);
}
$endgroup$
add a comment |
$begingroup$
Some things are repeated:
days - weeks * 7
hours - days * 24
minutes - hours * 60
These can and should be made into their own variables - but what you are really after seems to be
days % 7
hours % 24
minutes % 60
You can replace:
double hours = diff.Hours + days * 24;
with
double hours = diff.TotalHours;
There is also a TotalMinutes. You can just use the Math.Floor() of these values to get an int.
I see that you are going for a single exit point for this function, but I think that readability would be improved if you got some of the simpler paths shorter:
if (minutes <= 1)
return "Just Now";
if (years >= 1) {
if (years >= 2) {
return years.ToString() + " years ago";
} else {
return "1 year ago";
}
EDIT to add:
There's a repeated block of code that could be refactored to its own function:
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
The body of the extracted function would look like:
if (smallUnitCount > 0) {
if (smallUnitCount > 1) {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitPluralName);
} else {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitSingularName);
}
}
if (largeUnitCount >= 2) {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitPluralName, stringy);
} else {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitSingularName, stringy);
}
$endgroup$
add a comment |
$begingroup$
Some things are repeated:
days - weeks * 7
hours - days * 24
minutes - hours * 60
These can and should be made into their own variables - but what you are really after seems to be
days % 7
hours % 24
minutes % 60
You can replace:
double hours = diff.Hours + days * 24;
with
double hours = diff.TotalHours;
There is also a TotalMinutes. You can just use the Math.Floor() of these values to get an int.
I see that you are going for a single exit point for this function, but I think that readability would be improved if you got some of the simpler paths shorter:
if (minutes <= 1)
return "Just Now";
if (years >= 1) {
if (years >= 2) {
return years.ToString() + " years ago";
} else {
return "1 year ago";
}
EDIT to add:
There's a repeated block of code that could be refactored to its own function:
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
The body of the extracted function would look like:
if (smallUnitCount > 0) {
if (smallUnitCount > 1) {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitPluralName);
} else {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitSingularName);
}
}
if (largeUnitCount >= 2) {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitPluralName, stringy);
} else {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitSingularName, stringy);
}
$endgroup$
Some things are repeated:
days - weeks * 7
hours - days * 24
minutes - hours * 60
These can and should be made into their own variables - but what you are really after seems to be
days % 7
hours % 24
minutes % 60
You can replace:
double hours = diff.Hours + days * 24;
with
double hours = diff.TotalHours;
There is also a TotalMinutes. You can just use the Math.Floor() of these values to get an int.
I see that you are going for a single exit point for this function, but I think that readability would be improved if you got some of the simpler paths shorter:
if (minutes <= 1)
return "Just Now";
if (years >= 1) {
if (years >= 2) {
return years.ToString() + " years ago";
} else {
return "1 year ago";
}
EDIT to add:
There's a repeated block of code that could be refactored to its own function:
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
The body of the extracted function would look like:
if (smallUnitCount > 0) {
if (smallUnitCount > 1) {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitPluralName);
} else {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitSingularName);
}
}
if (largeUnitCount >= 2) {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitPluralName, stringy);
} else {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitSingularName, stringy);
}
edited May 31 '11 at 20:36
answered May 31 '11 at 19:49
Jeff PaulsenJeff Paulsen
32114
32114
add a comment |
add a comment |
$begingroup$
I would use casting double
to int
instead of Floor
in your case. Firstly because I'm a little bit cautious about equality comparison of doubles in years >= 1
. I would write it in this way:
int years = (int)(diff.TotalDays/365);
$endgroup$
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
1
$begingroup$
Yep, with positive doubles casting toint
doesFloor
exactly. See Explicit conversion section here. It has exactly your sample.
$endgroup$
– Snowbear
May 31 '11 at 21:48
add a comment |
$begingroup$
I would use casting double
to int
instead of Floor
in your case. Firstly because I'm a little bit cautious about equality comparison of doubles in years >= 1
. I would write it in this way:
int years = (int)(diff.TotalDays/365);
$endgroup$
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
1
$begingroup$
Yep, with positive doubles casting toint
doesFloor
exactly. See Explicit conversion section here. It has exactly your sample.
$endgroup$
– Snowbear
May 31 '11 at 21:48
add a comment |
$begingroup$
I would use casting double
to int
instead of Floor
in your case. Firstly because I'm a little bit cautious about equality comparison of doubles in years >= 1
. I would write it in this way:
int years = (int)(diff.TotalDays/365);
$endgroup$
I would use casting double
to int
instead of Floor
in your case. Firstly because I'm a little bit cautious about equality comparison of doubles in years >= 1
. I would write it in this way:
int years = (int)(diff.TotalDays/365);
answered May 31 '11 at 21:30
SnowbearSnowbear
3,51311423
3,51311423
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
1
$begingroup$
Yep, with positive doubles casting toint
doesFloor
exactly. See Explicit conversion section here. It has exactly your sample.
$endgroup$
– Snowbear
May 31 '11 at 21:48
add a comment |
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
1
$begingroup$
Yep, with positive doubles casting toint
doesFloor
exactly. See Explicit conversion section here. It has exactly your sample.
$endgroup$
– Snowbear
May 31 '11 at 21:48
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
$begingroup$
would doing so accomplish the same as Floor? that is, would casting .8 to an int return 0? Because that's important (i don't want .8 to round to 1 and have the function say that it's been a year when it's only really been 80% of a year)
$endgroup$
– Thomas Shields
May 31 '11 at 21:35
1
1
$begingroup$
Yep, with positive doubles casting to
int
does Floor
exactly. See Explicit conversion section here. It has exactly your sample.$endgroup$
– Snowbear
May 31 '11 at 21:48
$begingroup$
Yep, with positive doubles casting to
int
does Floor
exactly. See Explicit conversion section here. It has exactly your sample.$endgroup$
– Snowbear
May 31 '11 at 21:48
add a comment |
$begingroup$
You can make it an extension, so you can do
string result = DateTime.Now.GetTimeSpan();
Here is how I did it a few time ago
/// <summary>
/// Provide extentions for the DateTime Object.
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// Gets the relative time for a datetime.
/// </summary>
/// <param name="dateTime">The datetime to get the relative time.</param>
/// <returns>A relative time in english.</returns>
public static string GetTimeSpan(this DateTime dateTime)
{
TimeSpan diff = DateTime.Now.Subtract(dateTime);
if (diff.TotalMinutes < 1)
{
return string.Format("{0:D2} second{1} ago", diff.Seconds, PluralizeIfNeeded(diff.Seconds));
}
if (diff.TotalHours < 1)
{
return string.Format("{0:D2} minute{1} ago", diff.Minutes, PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays < 1)
{
return string.Format("{0:D2} hour{2} and {1:D2} minute{3} ago", diff.Hours, diff.Minutes, PluralizeIfNeeded(diff.Hours), PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 2)
{
return string.Format(
"{0:D2} day{3}, {1:D2} hour{4} and {2:D2} minute{5} ago",
diff.Days,
diff.Hours,
diff.Minutes,
PluralizeIfNeeded(diff.Days),
PluralizeIfNeeded(diff.Hours),
PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 30)
{
return string.Format("{0:D2} days ago", diff.TotalDays);
}
return string.Format("{0:g}", dateTime);
}
/// <summary>
/// Gets a 's' if value is > 1.
/// </summary>
/// <param name="testValue">The value to test.</param>
/// <returns>An 's' if value is > 1, otherwise an empty string.</returns>
private static string PluralizeIfNeeded(int testValue)
{
return testValue > 1 ? "s" : string.Empty;
}
}
$endgroup$
add a comment |
$begingroup$
You can make it an extension, so you can do
string result = DateTime.Now.GetTimeSpan();
Here is how I did it a few time ago
/// <summary>
/// Provide extentions for the DateTime Object.
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// Gets the relative time for a datetime.
/// </summary>
/// <param name="dateTime">The datetime to get the relative time.</param>
/// <returns>A relative time in english.</returns>
public static string GetTimeSpan(this DateTime dateTime)
{
TimeSpan diff = DateTime.Now.Subtract(dateTime);
if (diff.TotalMinutes < 1)
{
return string.Format("{0:D2} second{1} ago", diff.Seconds, PluralizeIfNeeded(diff.Seconds));
}
if (diff.TotalHours < 1)
{
return string.Format("{0:D2} minute{1} ago", diff.Minutes, PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays < 1)
{
return string.Format("{0:D2} hour{2} and {1:D2} minute{3} ago", diff.Hours, diff.Minutes, PluralizeIfNeeded(diff.Hours), PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 2)
{
return string.Format(
"{0:D2} day{3}, {1:D2} hour{4} and {2:D2} minute{5} ago",
diff.Days,
diff.Hours,
diff.Minutes,
PluralizeIfNeeded(diff.Days),
PluralizeIfNeeded(diff.Hours),
PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 30)
{
return string.Format("{0:D2} days ago", diff.TotalDays);
}
return string.Format("{0:g}", dateTime);
}
/// <summary>
/// Gets a 's' if value is > 1.
/// </summary>
/// <param name="testValue">The value to test.</param>
/// <returns>An 's' if value is > 1, otherwise an empty string.</returns>
private static string PluralizeIfNeeded(int testValue)
{
return testValue > 1 ? "s" : string.Empty;
}
}
$endgroup$
add a comment |
$begingroup$
You can make it an extension, so you can do
string result = DateTime.Now.GetTimeSpan();
Here is how I did it a few time ago
/// <summary>
/// Provide extentions for the DateTime Object.
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// Gets the relative time for a datetime.
/// </summary>
/// <param name="dateTime">The datetime to get the relative time.</param>
/// <returns>A relative time in english.</returns>
public static string GetTimeSpan(this DateTime dateTime)
{
TimeSpan diff = DateTime.Now.Subtract(dateTime);
if (diff.TotalMinutes < 1)
{
return string.Format("{0:D2} second{1} ago", diff.Seconds, PluralizeIfNeeded(diff.Seconds));
}
if (diff.TotalHours < 1)
{
return string.Format("{0:D2} minute{1} ago", diff.Minutes, PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays < 1)
{
return string.Format("{0:D2} hour{2} and {1:D2} minute{3} ago", diff.Hours, diff.Minutes, PluralizeIfNeeded(diff.Hours), PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 2)
{
return string.Format(
"{0:D2} day{3}, {1:D2} hour{4} and {2:D2} minute{5} ago",
diff.Days,
diff.Hours,
diff.Minutes,
PluralizeIfNeeded(diff.Days),
PluralizeIfNeeded(diff.Hours),
PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 30)
{
return string.Format("{0:D2} days ago", diff.TotalDays);
}
return string.Format("{0:g}", dateTime);
}
/// <summary>
/// Gets a 's' if value is > 1.
/// </summary>
/// <param name="testValue">The value to test.</param>
/// <returns>An 's' if value is > 1, otherwise an empty string.</returns>
private static string PluralizeIfNeeded(int testValue)
{
return testValue > 1 ? "s" : string.Empty;
}
}
$endgroup$
You can make it an extension, so you can do
string result = DateTime.Now.GetTimeSpan();
Here is how I did it a few time ago
/// <summary>
/// Provide extentions for the DateTime Object.
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// Gets the relative time for a datetime.
/// </summary>
/// <param name="dateTime">The datetime to get the relative time.</param>
/// <returns>A relative time in english.</returns>
public static string GetTimeSpan(this DateTime dateTime)
{
TimeSpan diff = DateTime.Now.Subtract(dateTime);
if (diff.TotalMinutes < 1)
{
return string.Format("{0:D2} second{1} ago", diff.Seconds, PluralizeIfNeeded(diff.Seconds));
}
if (diff.TotalHours < 1)
{
return string.Format("{0:D2} minute{1} ago", diff.Minutes, PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays < 1)
{
return string.Format("{0:D2} hour{2} and {1:D2} minute{3} ago", diff.Hours, diff.Minutes, PluralizeIfNeeded(diff.Hours), PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 2)
{
return string.Format(
"{0:D2} day{3}, {1:D2} hour{4} and {2:D2} minute{5} ago",
diff.Days,
diff.Hours,
diff.Minutes,
PluralizeIfNeeded(diff.Days),
PluralizeIfNeeded(diff.Hours),
PluralizeIfNeeded(diff.Minutes));
}
if (diff.TotalDays <= 30)
{
return string.Format("{0:D2} days ago", diff.TotalDays);
}
return string.Format("{0:g}", dateTime);
}
/// <summary>
/// Gets a 's' if value is > 1.
/// </summary>
/// <param name="testValue">The value to test.</param>
/// <returns>An 's' if value is > 1, otherwise an empty string.</returns>
private static string PluralizeIfNeeded(int testValue)
{
return testValue > 1 ? "s" : string.Empty;
}
}
answered Jun 1 '11 at 9:48
SamSam
11
11
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f2738%2fpretty-date-generator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown