C # හි සාපේක්ෂ කාලය ගණනය කරන්න


1527

නිශ්චිත DateTimeඅගයක් ලබා දී, සාපේක්ෂ කාලය පෙන්වන්නේ කෙසේද, වැනි:

  • පැය 2 කට පෙර
  • දින 3 කට පෙර
  • මාසයකට පෙර

80
මෙතැන් සිට අනාගතය දක්වා සාපේක්ෂ කාලයක් ගණනය කිරීමට ඔබට අවශ්‍ය නම් කුමක් කළ යුතුද?
ජොනී ඩී. කැනෝ -ලෙෆ්ට්වෙයාර්-

2
moment.js යනු ඉතා හොඳ දිනය විග්‍රහ කරන පුස්තකාලයකි .. ඔබේ අවශ්‍යතා මත පදනම්ව (සේවාදායක පැත්ත හෝ සේවාදායකයාගේ පැත්ත) භාවිතා කිරීම සලකා බැලිය හැකිය. කිසිවෙකු මෙහි සඳහන් කර නැති නිසා
මාටෙජ්

2
.Net පැකේජය github.com/NickStrupat/TimeAgo ඇත, එය ඉල්ලන දේ බොහෝ සෙයින් කරයි.
රොස්කෝ

දිනය හැඩතල ගැන්වීම සඳහා මෙම ව්‍යාපෘතිය ඉතා සිනිඳුයි github.com/Humanizr/Humanizer#humanize-datetime
ආරොන් හුඩන්

Answers:


994

ජෙෆ්, ඔබේ කේතය හොඳයි, නමුත් නියතයන් සමඟ වඩා පැහැදිලි විය හැකිය (කේතය සම්පුර්ණ කර ඇති පරිදි).

const int SECOND = 1;
const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;

var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);
double delta = Math.Abs(ts.TotalSeconds);

if (delta < 1 * MINUTE)
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";

if (delta < 2 * MINUTE)
  return "a minute ago";

if (delta < 45 * MINUTE)
  return ts.Minutes + " minutes ago";

if (delta < 90 * MINUTE)
  return "an hour ago";

if (delta < 24 * HOUR)
  return ts.Hours + " hours ago";

if (delta < 48 * HOUR)
  return "yesterday";

if (delta < 30 * DAY)
  return ts.Days + " days ago";

if (delta < 12 * MONTH)
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
  return years <= 1 ? "one year ago" : years + " years ago";
}

220
මම එවැනි නියතයන්ට වෛර කරමි. මෙය කිසිවෙකුට වැරදිද? Thread.Sleep(1 * MINUTE)? එය 1000 ක සාධකයකින් වැරදියි.
රෝමන් ස්ටාර්කොව්

31
const int SECOND = 1;ඉතින් අමුතු තත්පරයක් තත්පරයක්.
seriousdev

64
මෙම වර්ගයේ කේත දේශීයකරණය කිරීමට නොහැකි තරම්ය. ඔබගේ යෙදුමට අවශ්‍ය වන්නේ ඉංග්‍රීසියෙන් නම්, හොඳයි. නමුත් ඔබ වෙනත් භාෂාවලට පනින්නේ නම්, මේ වගේ තර්කනය කිරීම ගැන ඔබ ඔබටම වෛර කරනු ඇත. ඉතින් ඔබ දන්නවා ...
නික් රීමන්

73
මම හිතන්නේ නියතයන් ඒවායේ ඇති වටිනාකම නිවැරදිව විස්තර කිරීම සඳහා නම් කරන ලද්දේ නම් එය තේරුම් ගැනීම පහසු වනු ඇත. එබැවින් SecondsPerMinute = 60; MinitsPerHour = 60; තත්පරපර්හූර් = මිනිත්තුපර්හර් * තත්පර තත්පර පැය; ආදිය MINUTE = 60 ලෙස හැඳින්වීමෙන් වටිනාකම කුමක්දැයි තීරණය කිරීමට පා er කයාට ඉඩ නොදේ.
ස්ලොලයිෆ්

14
වැරදි 'ඊයේ' හෝ 'දිනකට පෙර' වටිනාකම ගැන කිසිවෙකු (ජෝ හැර) සැලකිලිමත් නොවන්නේ ඇයි ??? ඊයේ පැයක් ගණනය කිරීමක් නොව එදිනෙදා ගණනය කිරීමකි. ඉතින් ඔව්, මෙය අවම වශයෙන් අවස්ථා දෙකකදීවත් වැරදි කේතයකි.
CtrlX

363

jquery.timeago ප්ලගිනය

ජෙෆ්, ස්ටැක් පිටාර ගැලීම jQuery පුළුල් ලෙස භාවිතා කරන නිසා, මම නිර්දේශ කරන්නේ jquery.timeago ප්ලගිනයයි .

ප්‍රතිලාභ:

  • මිනිත්තු 10 කට පෙර පිටුව විවෘත කළද "මිනිත්තු 1 කට පෙර" කාලරාමු වලින් වළකින්න; timeago ස්වයංක්‍රීයව නැවුම් කරයි.
  • ඔබගේ වෙබ් යෙදුම්වල පිටුව සහ / හෝ කොටස් හැඹිලියෙන් ඔබට උපරිම ප්‍රයෝජන ගත හැකිය, මන්ද සේවාදායකයේ කාලරාමු ගණනය නොකෙරේ.
  • සිසිල් ළමයින් වැනි ක්ෂුද්‍ර ආකෘති භාවිතා කිරීමට ඔබට සිදුවේ.

DOM හි ඔබගේ කාලරාමුවලට එය අමුණන්න:

jQuery(document).ready(function() {
    jQuery('abbr.timeago').timeago();
});

මෙමඟින් සියලුම abbrඅංගයන් ටයිමගෝ පන්තියක් සහ අයිඑස්ඕ 8601 කාලරාමුව සමඟ හරවනු ඇත :

<abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr>

මේ වගේ දෙයකට:

<abbr class="timeago" title="July 17, 2008">4 months ago</abbr>

අස්වැන්න: මාස 4 කට පෙර. කාලය ගෙවී යත්ම, කාලරාමු ස්වයංක්‍රීයව යාවත්කාලීන වේ.

වියාචනය: මම මෙම ප්ලගිනය ලිව්වෙමි, එබැවින් මම පක්ෂග්‍රාහී වෙමි.


39
සෙබ්, ඔබ ජාවාස්ක්‍රිප්ට් අක්‍රීය කර ඇත්නම්, ඔබ මුලින් ඇබ්‍රා ටැග් අතර තැබූ නූල දර්ශණය වේ. සාමාන්‍යයෙන්, මෙය ඔබ කැමති ඕනෑම ආකෘතියක දිනයක් හෝ වේලාවක් පමණි. ටයිමගෝ සුන්දර ලෙස පිරිහෙයි. එය එතරම් සරල නොවේ.
රයන් මැක්ගරි

23
රයන්, මම යෝජනා කළා SO ටික වේලාවකට පෙර ටයිමගෝ භාවිතා කරන්න කියලා. ජෙෆ්ගේ ප්‍රතිචාරය නිසා මා අ cry න්නට විය, මම ඔබට වාඩි වන ලෙස යෝජනා කරමි: stackoverflow.uservoice.com/pages/1722-general/suggestions/…
රොබ් ෆොන්සෙකා-එන්සර්

7
හෙහ්, ස්තූතියි රොබ්. ඒක හරි. SO පිටු වල කාලරාමු විශාල ප්‍රමාණයක් තිබුණද, සංක්‍රාන්ති සමයේදී එක් අංකයක් පමණක් වෙනස් වන විට එය යන්තම් කැපී පෙනේ. ස්වයංක්‍රීය යාවත්කාලීනයන් වළක්වා ගැනීමට ඔහු තෝරා ගත්තද, පිටු හැඹිලියේ ප්‍රයෝජන ඔහු අවම වශයෙන් අගය කරනු ඇතැයි මම සිතුවෙමි. මට විශ්වාසයි ජෙෆ්ට ප්ලගිනය වැඩි දියුණු කිරීම සඳහා ප්‍රතිපෝෂණ ලබා දිය හැකිව තිබුණි. Arstechnica.com වැනි වෙබ් අඩවි භාවිතා කරන බව මම දනිමි .
රයන් මැක්ගරි

19
Ob රොබ් ෆොන්සෙකා-එන්සර් - දැන් එය මා ද අ cry නවා. කොහොමද යාවත්කාලීන වරක් විනාඩියකට, නිවැරදි තොරතුරු පෙන්වන්න වේ කිසිම ආකාරයකින් දෙවන වරක් යෙදූ පෙළ සම්බන්ධ?
ඩැනියෙල් අර්විකර්

26
ප්‍රශ්නය C # ගැන ය, jQuery ප්ලගිනයක් අදාළ වන්නේ කෙසේදැයි බැලීමට මා අසමත් වේ.
බාර්ටොස්කේපී

332

මෙන්න මම එය කරන ආකාරය

var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks);
double delta = Math.Abs(ts.TotalSeconds);

if (delta < 60)
{
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 60 * 2)
{
  return "a minute ago";
}
if (delta < 45 * 60)
{
  return ts.Minutes + " minutes ago";
}
if (delta < 90 * 60)
{
  return "an hour ago";
}
if (delta < 24 * 60 * 60)
{
  return ts.Hours + " hours ago";
}
if (delta < 48 * 60 * 60)
{
  return "yesterday";
}
if (delta < 30 * 24 * 60 * 60)
{
  return ts.Days + " days ago";
}
if (delta < 12 * 30 * 24 * 60 * 60)
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "one year ago" : years + " years ago";

යෝජනා? අදහස්? මෙම ඇල්ගොරිතම වැඩි දියුණු කිරීමට ක්‍රම?


112
"<48 * 60 * 60s" යනු "ඊයේ" සඳහා තරමක් සාම්ප්‍රදායික නොවන අර්ථ දැක්වීමකි. එය බදාදා උදේ 9 නම්, ඔබ ඇත්තටම සඳුදා උදේ 9:01 "ඊයේ" ලෙස සිතනවාද? මම සිතුවේ ඊයේ හෝ "දින කිහිපයකට පෙර" ඇල්ගොරිතමයක් මධ්‍යම රාත්‍රියට පෙර / පසුව සලකා බැලිය යුතු බවයි.
ජෝ

140
සම්පාදකයින් සාමාන්‍යයෙන් 24 * 60 * 60 වැනි නියත ප්‍රකාශන පූර්ව ගණනය කිරීමේදී ඉතා හොඳයි, එබැවින් ඔබට එය 86400 ලෙස ගණනය කර මුල් ප්‍රකාශනය අදහස් දැක්වීම් වෙනුවට සෘජුවම භාවිතා කළ හැකිය
zvolkov

11
zbzlm මම හිතන්නේ මම වැඩ කරමින් සිටි ව්‍යාපෘතියක් සඳහා. මෙහි මගේ අභිප්‍රාය වූයේ මෙම කේත නියැදියෙන් සති ඉවත් කර ඇති බව අන් අයට දැනුම් දීමයි. එය කරන්නේ කෙසේද යන්න සම්බන්ධයෙන්, එය මට කෙළින්ම ඉදිරියෙන් සිටින බවක් පෙනෙන්නට තිබුණි.
jray

9
ඇල්ගොරිතම වැඩි දියුණු කිරීම සඳහා හොඳ ක්‍රමයක් වන්නේ නිරවද්‍යතාව වැඩි කිරීම සඳහා "මාස 2 දින 21 කට පෙර", "පැය 1 විනාඩි 40 කට පෙර" වැනි ඒකක 2 ක් ප්‍රදර්ශනය කිරීමයි.
එව්ගනි ලෙවින්

6
@ ජෙෆි, අධික වසර සහ ඒ හා සම්බන්ධ චෙක්පත් සඳහා ගණනය කිරීම ඔබට මග හැරුණි
සබූර් අවාන්

93
public static string RelativeDate(DateTime theDate)
{
    Dictionary<long, string> thresholds = new Dictionary<long, string>();
    int minute = 60;
    int hour = 60 * minute;
    int day = 24 * hour;
    thresholds.Add(60, "{0} seconds ago");
    thresholds.Add(minute * 2, "a minute ago");
    thresholds.Add(45 * minute, "{0} minutes ago");
    thresholds.Add(120 * minute, "an hour ago");
    thresholds.Add(day, "{0} hours ago");
    thresholds.Add(day * 2, "yesterday");
    thresholds.Add(day * 30, "{0} days ago");
    thresholds.Add(day * 365, "{0} months ago");
    thresholds.Add(long.MaxValue, "{0} years ago");
    long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;
    foreach (long threshold in thresholds.Keys) 
    {
        if (since < threshold) 
        {
            TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks));
            return string.Format(thresholds[threshold], (t.Days > 365 ? t.Days / 365 : (t.Days > 0 ? t.Days : (t.Hours > 0 ? t.Hours : (t.Minutes > 0 ? t.Minutes : (t.Seconds > 0 ? t.Seconds : 0))))).ToString());
        }
    }
    return "";
}

මෙම අනුවාදයේ සංක්ෂිප්තභාවය සහ නව ටික් ලකුණු එකතු කිරීමේ හැකියාව සඳහා මම කැමැත්තෙමි. මෙය Latest()දිගු ලයිනර් 1 වෙනුවට ටයිම්ස්පන් වෙත දිගුවක් සමඟ සංයුක්ත කළ හැකි නමුත්, පළකිරීමේ සංක්ෂිප්තය සඳහා මෙය සිදු වේ. මෙය පැය 1 කට පෙර, පැය 1 කට පෙර, පැය 2 ක් ගතවන තුරු පැයක් ලබා දීමෙන් නිවැරදි කරයි


මෙම ශ්‍රිතය භාවිතා කරමින් මට සියලු ආකාරයේ ගැටලු තිබේ, උදාහරණයක් ලෙස ඔබ 'theDate = DateTime.Now.AddMinutes (-40);' මට ලැබෙන්නේ 'පැය 40 කට පෙර', නමුත් මයිකල්ගේ ප්‍රතික්‍රියාකාරක ප්‍රතිචාරයත් සමඟ එය 'මිනිත්තු 40 කට පෙර' නිවැරදිව ආපසු එයිද?
ගොනේල්

මම හිතන්නේ ඔබට බිංදුවක් නැති වී ඇති බව උත්සාහ කරන්න: දිගු කලක් සිට = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;
robnardo

8
හ්ම්, මෙම කේතය ක්‍රියාත්මක විය හැකි අතර ශබ්ද කෝෂයේ යතුරු අනුපිළිවෙල නිශ්චිත අනුපිළිවෙලකට ඇතැයි උපකල්පනය කිරීම වැරදිය. ශබ්දකෝෂය Object.GetHashCode () භාවිතා කරයි, එය දිගු නමුත් int නොවේ. මේවා වර්ග කිරීමට ඔබට අවශ්‍ය නම් ඔබ වර්ග කළ ලැයිස්තුවක් <දිගු, නූල්> භාවිතා කළ යුතුය. එළිපත්ත නම් / වෙනත් නම් /.../ කට්ටලයකින් ඇගයීමෙහි වරද කුමක්ද? ඔබට සමාන සැසඳීම් සංඛ්‍යාවක් ලැබේ. දිගු කලක් තිස්සේ FYI හෑෂ්.මැක්ස් අගය int.MinValue හා සමාන වේ.
CodeMonkeyKing

OP අමතක වී ඇත t.Days> 30? t.Days / 30:
Lars Holm Jensen

OdeCodeMonkeyKing විසින් සඳහන් කර ඇති ගැටළුව නිරාකරණය කිරීම සඳහා, ඔබට SortedDictionaryතැනිතලා වෙනුවට ආදේශකයක් භාවිතා කළ හැකිය Dictionary: භාවිතය එක හා සමානයි, නමුත් යතුරු වර්ග කර ඇති බව සහතික කරයි. නමුත් ඒ සඳහා පවා, මෙම ඇල්ගොරිතමය අඩුපාඩු නිසා ඇති RelativeDate(DateTime.Now.AddMonths(-3).AddDays(-3))ප්රතිලාභ "මාස 95 කට පෙර" , නොතකා ඔබ වැරදි වන භාවිතා කරන්නේ කුමන ශබ්ද කෝෂය වර්ගය (එය ආපසු යුතු "මාස 3 කට පෙර" හෝ 'වන සීමාව, ඔබ මත පදනම්ව "මාස 4 කට පෙර" නැවත භාවිතා කිරීම) - -3 පසුගිය වර්ෂයේ දිනයක් නිර්මාණය නොකළද (මම මෙය දෙසැම්බර් මාසයේදී අත්හදා බැලුවෙමි, එබැවින් එය සිදු නොවිය යුතුය).
මැට්

72

PHP සඳහා ජෙෆ්ස් ස්ක්‍රිප්ට් වෙතින් නැවත ලිවීම:

define("SECOND", 1);
define("MINUTE", 60 * SECOND);
define("HOUR", 60 * MINUTE);
define("DAY", 24 * HOUR);
define("MONTH", 30 * DAY);
function relativeTime($time)
{   
    $delta = time() - $time;

    if ($delta < 1 * MINUTE)
    {
        return $delta == 1 ? "one second ago" : $delta . " seconds ago";
    }
    if ($delta < 2 * MINUTE)
    {
      return "a minute ago";
    }
    if ($delta < 45 * MINUTE)
    {
        return floor($delta / MINUTE) . " minutes ago";
    }
    if ($delta < 90 * MINUTE)
    {
      return "an hour ago";
    }
    if ($delta < 24 * HOUR)
    {
      return floor($delta / HOUR) . " hours ago";
    }
    if ($delta < 48 * HOUR)
    {
      return "yesterday";
    }
    if ($delta < 30 * DAY)
    {
        return floor($delta / DAY) . " days ago";
    }
    if ($delta < 12 * MONTH)
    {
      $months = floor($delta / DAY / 30);
      return $months <= 1 ? "one month ago" : $months . " months ago";
    }
    else
    {
        $years = floor($delta / DAY / 365);
        return $years <= 1 ? "one year ago" : $years . " years ago";
    }
}    

7
ප්‍රශ්නය C # ටැග් කර ඇත්තේ ඇයි PHP කේතය ?
කික්නෙට්

66
public static string ToRelativeDate(DateTime input)
{
    TimeSpan oSpan = DateTime.Now.Subtract(input);
    double TotalMinutes = oSpan.TotalMinutes;
    string Suffix = " ago";

    if (TotalMinutes < 0.0)
    {
        TotalMinutes = Math.Abs(TotalMinutes);
        Suffix = " from now";
    }

    var aValue = new SortedList<double, Func<string>>();
    aValue.Add(0.75, () => "less than a minute");
    aValue.Add(1.5, () => "about a minute");
    aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes)));
    aValue.Add(90, () => "about an hour");
    aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24
    aValue.Add(2880, () => "a day"); // 60 * 48
    aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30
    aValue.Add(86400, () => "about a month"); // 60 * 24 * 60
    aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365 
    aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2
    aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));

    return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix;
}

http://refactormycode.com/codes/493-twitter-esque-relative-dates

සී # 6 අනුවාදය:

static readonly SortedList<double, Func<TimeSpan, string>> offsets = 
   new SortedList<double, Func<TimeSpan, string>>
{
    { 0.75, _ => "less than a minute"},
    { 1.5, _ => "about a minute"},
    { 45, x => $"{x.TotalMinutes:F0} minutes"},
    { 90, x => "about an hour"},
    { 1440, x => $"about {x.TotalHours:F0} hours"},
    { 2880, x => "a day"},
    { 43200, x => $"{x.TotalDays:F0} days"},
    { 86400, x => "about a month"},
    { 525600, x => $"{x.TotalDays / 30:F0} months"},
    { 1051200, x => "about a year"},
    { double.MaxValue, x => $"{x.TotalDays / 365:F0} years"}
};

public static string ToRelativeDate(this DateTime input)
{
    TimeSpan x = DateTime.Now - input;
    string Suffix = x.TotalMinutes > 0 ? " ago" : " from now";
    x = new TimeSpan(Math.Abs(x.Ticks));
    return offsets.First(n => x.TotalMinutes < n.Key).Value(x) + Suffix;
}

මෙය ඉතා හොඳයි IMO :) මෙය දිගු කිරීමේ ක්‍රමයක් ලෙසද ප්‍රතිනිර්මාණය කළ හැකිද? ශබ්දකෝෂය ස්ථිතික විය හැකි බැවින් එය එක් වරක් පමණක් නිර්මාණය කර එතැන් සිට යොමු කරනු ලැබේ.
Pure.Krome


5
ඔබට එම ශබ්ද කෝෂය ක්ෂේත්‍රයකට ඇද ගැනීමට අවශ්‍ය වනු ඇත, එවිට ඔබ ක්ෂණිකකරණය සහ ජී.සී. ඔබට වෙනස් Func<string>විය යුතුයි Func<double>.
ඩ්‍රූ නොක්ස්

49

ඩේට් ටයිම් පංතියට අනාගත හා අතීත දිනයන් හසුරුවන සහ ඔබ සොයන විස්තරයේ මට්ටම නියම කිරීමට ඔබට ඉඩ සලසන දළ වශයෙන් විකල්පයක් සපයන ඩේටයිම් පන්තියට මම එකතු කළ ක්‍රියාත්මක කිරීමක් මෙන්න ("පැය 3 කට පෙර" එදිරිව "පැය 3, මිනිත්තු 23, තත්පර 12 කට පෙර "):

using System.Text;

/// <summary>
/// Compares a supplied date to the current date and generates a friendly English 
/// comparison ("5 days ago", "5 days from now")
/// </summary>
/// <param name="date">The date to convert</param>
/// <param name="approximate">When off, calculate timespan down to the second.
/// When on, approximate to the largest round unit of time.</param>
/// <returns></returns>
public static string ToRelativeDateString(this DateTime value, bool approximate)
{
    StringBuilder sb = new StringBuilder();

    string suffix = (value > DateTime.Now) ? " from now" : " ago";

    TimeSpan timeSpan = new TimeSpan(Math.Abs(DateTime.Now.Subtract(value).Ticks));

    if (timeSpan.Days > 0)
    {
        sb.AppendFormat("{0} {1}", timeSpan.Days,
          (timeSpan.Days > 1) ? "days" : "day");
        if (approximate) return sb.ToString() + suffix;
    }
    if (timeSpan.Hours > 0)
    {
        sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty,
          timeSpan.Hours, (timeSpan.Hours > 1) ? "hours" : "hour");
        if (approximate) return sb.ToString() + suffix;
    }
    if (timeSpan.Minutes > 0)
    {
        sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty, 
          timeSpan.Minutes, (timeSpan.Minutes > 1) ? "minutes" : "minute");
        if (approximate) return sb.ToString() + suffix;
    }
    if (timeSpan.Seconds > 0)
    {
        sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty, 
          timeSpan.Seconds, (timeSpan.Seconds > 1) ? "seconds" : "second");
        if (approximate) return sb.ToString() + suffix;
    }
    if (sb.Length == 0) return "right now";

    sb.Append(suffix);
    return sb.ToString();
}

38

සේවාදායකයාගේ පැත්තෙන්ද මෙය ගණනය කිරීමට මම නිර්දේශ කරමි. සේවාදායකයා සඳහා අඩු වැඩ.

පහත දැක්වෙන්නේ මා භාවිතා කරන අනුවාදයයි (සාක් ලෙදර්මන් වෙතින්)

/*
 * Javascript Humane Dates
 * Copyright (c) 2008 Dean Landolt (deanlandolt.com)
 * Re-write by Zach Leatherman (zachleat.com)
 * 
 * Adopted from the John Resig's pretty.js
 * at http://ejohn.org/blog/javascript-pretty-date
 * and henrah's proposed modification 
 * at http://ejohn.org/blog/javascript-pretty-date/#comment-297458
 * 
 * Licensed under the MIT license.
 */

function humane_date(date_str){
        var time_formats = [
                [60, 'just now'],
                [90, '1 minute'], // 60*1.5
                [3600, 'minutes', 60], // 60*60, 60
                [5400, '1 hour'], // 60*60*1.5
                [86400, 'hours', 3600], // 60*60*24, 60*60
                [129600, '1 day'], // 60*60*24*1.5
                [604800, 'days', 86400], // 60*60*24*7, 60*60*24
                [907200, '1 week'], // 60*60*24*7*1.5
                [2628000, 'weeks', 604800], // 60*60*24*(365/12), 60*60*24*7
                [3942000, '1 month'], // 60*60*24*(365/12)*1.5
                [31536000, 'months', 2628000], // 60*60*24*365, 60*60*24*(365/12)
                [47304000, '1 year'], // 60*60*24*365*1.5
                [3153600000, 'years', 31536000], // 60*60*24*365*100, 60*60*24*365
                [4730400000, '1 century'] // 60*60*24*365*100*1.5
        ];

        var time = ('' + date_str).replace(/-/g,"/").replace(/[TZ]/g," "),
                dt = new Date,
                seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),
                token = ' ago',
                i = 0,
                format;

        if (seconds < 0) {
                seconds = Math.abs(seconds);
                token = '';
        }

        while (format = time_formats[i++]) {
                if (seconds < format[0]) {
                        if (format.length == 2) {
                                return format[1] + (i > 1 ? token : ''); // Conditional so we don't return Just Now Ago
                        } else {
                                return Math.round(seconds / format[2]) + ' ' + format[1] + (i > 1 ? token : '');
                        }
                }
        }

        // overflow for centuries
        if(seconds > 4730400000)
                return Math.round(seconds / 4730400000) + ' centuries' + token;

        return date_str;
};

if(typeof jQuery != 'undefined') {
        jQuery.fn.humane_dates = function(){
                return this.each(function(){
                        var date = humane_date(this.title);
                        if(date && jQuery(this).text() != date) // don't modify the dom if we don't have to
                                jQuery(this).text(date);
                });
        };
}

4
ප්‍රශ්නය C # ටැග් කර ඇත්තේ ඇයි ජාවාස්ක්‍රිප්ට් කේතය ?
කික්නෙට්

36

නුජෙට් හි හියුමනිසර් නමින් පැකේජයක් ද ඇත , එය සැබවින්ම හොඳින් ක්‍රියාත්මක වන අතර එය .NET පදනමේ ඇත.

DateTime.UtcNow.AddHours(-30).Humanize() => "yesterday"
DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"

DateTime.UtcNow.AddHours(30).Humanize() => "tomorrow"
DateTime.UtcNow.AddHours(2).Humanize() => "2 hours from now"

TimeSpan.FromMilliseconds(1299630020).Humanize() => "2 weeks"
TimeSpan.FromMilliseconds(1299630020).Humanize(3) => "2 weeks, 1 day, 1 hour"

ස්කොට් හැන්සල්මන්ට ඔහුගේ බ්ලොග් අඩවියේ එය ලිවීමක් තිබේ


3
මිත්‍රශීලී සටහන: .net 4.5 හෝ ඊට ඉහළින් සම්පූර්ණ මානවකරණය ස්ථාපනය නොකරන්න ... හියුමිනයිසර් ස්ථාපනය කරන්න. එහි කොටසක් පමණක් .. වෙනත් භාෂා පැකේජ සඳහා මෙම අනුවාදය සඳහා සහය නොදක්වන්න
අහමඩ්

එතරම් ප්‍රයෝජනවත්! මෙම පිළිතුර මෙම ලැයිස්තුවේ වඩා බෙහෙවින් වැඩි විය යුතුය. මට ඡන්ද 100 ක් තිබුණා නම් මම මේකට දෙන්නම්. පෙනෙන විදිහට (JS-land වෙතින් පැමිණීම), මෙම පැකේජය සෙවීම පහසු නොවීය.
කුමාර්හාර්ෂ්

29

ජෙෆ්

IMHO ඔබේ දිග ටිකක් දිගු බව පෙනේ. කෙසේ වෙතත් එය "ඊයේ" සහ "අවුරුදු" සඳහා ආධාරයෙන් තව ටිකක් ශක්තිමත් බව පෙනේ. නමුත් මෙය භාවිතා කරන විට මගේ අත්දැකීම් අනුව, පුද්ගලයා පළමු දින 30 තුළ අන්තර්ගතය බැලීමට බොහෝ දුරට ඉඩ ඇත. ඊට පසු පැමිණෙන්නේ සැබවින්ම දැඩි මතධාරීන් පමණි. ඉතින්, මම සාමාන්‍යයෙන් තෝරා ගන්නේ මෙය කෙටි හා සරල ලෙස තබා ගැනීමටයි.

මම දැනට මගේ වෙබ් අඩවියක භාවිතා කරන ක්‍රමය මෙයයි. මෙය ආපසු පැමිණෙන්නේ සාපේක්ෂ දිනයක්, පැය සහ වේලාව පමණි. එවිට පරිශීලකයාට ප්‍රතිදානයේදී "පෙර" මතට තට්ටු කළ යුතුය.

public static string ToLongString(this TimeSpan time)
{
    string output = String.Empty;

    if (time.Days > 0)
        output += time.Days + " days ";

    if ((time.Days == 0 || time.Days == 1) && time.Hours > 0)
        output += time.Hours + " hr ";

    if (time.Days == 0 && time.Minutes > 0)
        output += time.Minutes + " min ";

    if (output.Length == 0)
        output += time.Seconds + " sec";

    return output.Trim();
}

24

සාදයට වසර කිහිපයක් ප්‍රමාද වූ නමුත් අතීත හා අනාගත දිනයන් සඳහා මෙය කිරීමට මට අවශ්‍යතාවයක් තිබුණි, එබැවින් මම ජෙෆ්ගේ සහ වින්සන්ට්ගේ දේ මේ සඳහා ඒකාබද්ධ කළෙමි . එය ත්‍රිකෝණාකාර අතිශයෝක්තියක්! :)

public static class DateTimeHelper
    {
        private const int SECOND = 1;
        private const int MINUTE = 60 * SECOND;
        private const int HOUR = 60 * MINUTE;
        private const int DAY = 24 * HOUR;
        private const int MONTH = 30 * DAY;

        /// <summary>
        /// Returns a friendly version of the provided DateTime, relative to now. E.g.: "2 days ago", or "in 6 months".
        /// </summary>
        /// <param name="dateTime">The DateTime to compare to Now</param>
        /// <returns>A friendly string</returns>
        public static string GetFriendlyRelativeTime(DateTime dateTime)
        {
            if (DateTime.UtcNow.Ticks == dateTime.Ticks)
            {
                return "Right now!";
            }

            bool isFuture = (DateTime.UtcNow.Ticks < dateTime.Ticks);
            var ts = DateTime.UtcNow.Ticks < dateTime.Ticks ? new TimeSpan(dateTime.Ticks - DateTime.UtcNow.Ticks) : new TimeSpan(DateTime.UtcNow.Ticks - dateTime.Ticks);

            double delta = ts.TotalSeconds;

            if (delta < 1 * MINUTE)
            {
                return isFuture ? "in " + (ts.Seconds == 1 ? "one second" : ts.Seconds + " seconds") : ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
            }
            if (delta < 2 * MINUTE)
            {
                return isFuture ? "in a minute" : "a minute ago";
            }
            if (delta < 45 * MINUTE)
            {
                return isFuture ? "in " + ts.Minutes + " minutes" : ts.Minutes + " minutes ago";
            }
            if (delta < 90 * MINUTE)
            {
                return isFuture ? "in an hour" : "an hour ago";
            }
            if (delta < 24 * HOUR)
            {
                return isFuture ? "in " + ts.Hours + " hours" : ts.Hours + " hours ago";
            }
            if (delta < 48 * HOUR)
            {
                return isFuture ? "tomorrow" : "yesterday";
            }
            if (delta < 30 * DAY)
            {
                return isFuture ? "in " + ts.Days + " days" : ts.Days + " days ago";
            }
            if (delta < 12 * MONTH)
            {
                int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
                return isFuture ? "in " + (months <= 1 ? "one month" : months + " months") : months <= 1 ? "one month ago" : months + " months ago";
            }
            else
            {
                int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
                return isFuture ? "in " + (years <= 1 ? "one year" : years + " years") : years <= 1 ? "one year ago" : years + " years ago";
            }
        }
    }

21

ජාවා හි මෙය කිරීමට පහසු ක්‍රමයක් තිබේද? මෙම java.util.Dateපන්ති ඉතා සීමිත බව පෙනේ.

මෙන්න මගේ ඉක්මන් හා අපිරිසිදු ජාවා විසඳුම:

import java.util.Date;
import javax.management.timer.Timer;

String getRelativeDate(Date date) {     
  long delta = new Date().getTime() - date.getTime();
  if (delta < 1L * Timer.ONE_MINUTE) {
    return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta) + " seconds ago";
  }
  if (delta < 2L * Timer.ONE_MINUTE) {
    return "a minute ago";
  }
  if (delta < 45L * Timer.ONE_MINUTE) {
    return toMinutes(delta) + " minutes ago";
  }
  if (delta < 90L * Timer.ONE_MINUTE) {
    return "an hour ago";
  }
  if (delta < 24L * Timer.ONE_HOUR) {
    return toHours(delta) + " hours ago";
  }
  if (delta < 48L * Timer.ONE_HOUR) {
    return "yesterday";
  }
  if (delta < 30L * Timer.ONE_DAY) {
    return toDays(delta) + " days ago";
  }
  if (delta < 12L * 4L * Timer.ONE_WEEK) { // a month
    long months = toMonths(delta); 
    return months <= 1 ? "one month ago" : months + " months ago";
  }
  else {
    long years = toYears(delta);
    return years <= 1 ? "one year ago" : years + " years ago";
  }
}

private long toSeconds(long date) {
  return date / 1000L;
}

private long toMinutes(long date) {
  return toSeconds(date) / 60L;
}

private long toHours(long date) {
  return toMinutes(date) / 60L;
}

private long toDays(long date) {
  return toHours(date) / 24L;
}

private long toMonths(long date) {
  return toDays(date) / 30L;
}

private long toYears(long date) {
  return toMonths(date) / 365L;
}

1
ප්‍රශ්නය C # ටැග් කර ඇත්තේ ඇයි ජාවා කේතය ?
කික්නෙට්

20

iPhone Objective-C අනුවාදය

+ (NSString *)timeAgoString:(NSDate *)date {
    int delta = -(int)[date timeIntervalSinceNow];

    if (delta < 60)
    {
        return delta == 1 ? @"one second ago" : [NSString stringWithFormat:@"%i seconds ago", delta];
    }
    if (delta < 120)
    {
        return @"a minute ago";
    }
    if (delta < 2700)
    {
        return [NSString stringWithFormat:@"%i minutes ago", delta/60];
    }
    if (delta < 5400)
    {
        return @"an hour ago";
    }
    if (delta < 24 * 3600)
    {
        return [NSString stringWithFormat:@"%i hours ago", delta/3600];
    }
    if (delta < 48 * 3600)
    {
        return @"yesterday";
    }
    if (delta < 30 * 24 * 3600)
    {
        return [NSString stringWithFormat:@"%i days ago", delta/(24*3600)];
    }
    if (delta < 12 * 30 * 24 * 3600)
    {
        int months = delta/(30*24*3600);
        return months <= 1 ? @"one month ago" : [NSString stringWithFormat:@"%i months ago", months];
    }
    else
    {
        int years = delta/(12*30*24*3600);
        return years <= 1 ? @"one year ago" : [NSString stringWithFormat:@"%i years ago", years];
    }
}

19

ලෝකය සහ ඇගේ ස්වාමිපුරුෂයා කේත සාම්පල පළ කරන බවක් පෙනෙන්නට ඇති හෙයින්, මෙම පිළිතුරු කිහිපයක් මත පදනම්ව මා මීට ටික කලකට පෙර ලියා ඇති දේ මෙන්න.

මෙම කේතය දේශීයකරණය කළ හැකි වීමට මට නිශ්චිත අවශ්‍යතාවයක් තිබුණි. එබැවින් මට පන්ති දෙකක් තිබේ - Grammarඑය දේශීයකරණය කළ හැකි නියමයන් නියම කරයි, සහ දීර් FuzzyDateExtensionsextension කිරීමේ ක්‍රම රාශියක් දරයි. අනාගත දින වකවානු සමඟ කටයුතු කිරීමට මට අවශ්‍යතාවයක් නොතිබුණි, එබැවින් මෙම කේතය සමඟ ඒවා හැසිරවීමට කිසිදු උත්සාහයක් නොගනී.

මම XMLdoc සමහරක් ප්‍රභවයේ තබා ඇත, නමුත් බොහෝ ඒවා ඉවත් කර ඇත (ඒවා පැහැදිලිව පෙනෙන තැන) සංක්ෂිප්තතාවය නිසා. මම සෑම පන්ති සාමාජිකයෙකුම මෙහි ඇතුළත් කර නැත:

public class Grammar
{
    /// <summary> Gets or sets the term for "just now". </summary>
    public string JustNow { get; set; }
    /// <summary> Gets or sets the term for "X minutes ago". </summary>
    /// <remarks>
    ///     This is a <see cref="String.Format"/> pattern, where <c>{0}</c>
    ///     is the number of minutes.
    /// </remarks>
    public string MinutesAgo { get; set; }
    public string OneHourAgo { get; set; }
    public string HoursAgo { get; set; }
    public string Yesterday { get; set; }
    public string DaysAgo { get; set; }
    public string LastMonth { get; set; }
    public string MonthsAgo { get; set; }
    public string LastYear { get; set; }
    public string YearsAgo { get; set; }
    /// <summary> Gets or sets the term for "ages ago". </summary>
    public string AgesAgo { get; set; }

    /// <summary>
    ///     Gets or sets the threshold beyond which the fuzzy date should be
    ///     considered "ages ago".
    /// </summary>
    public TimeSpan AgesAgoThreshold { get; set; }

    /// <summary>
    ///     Initialises a new <see cref="Grammar"/> instance with the
    ///     specified properties.
    /// </summary>
    private void Initialise(string justNow, string minutesAgo,
        string oneHourAgo, string hoursAgo, string yesterday, string daysAgo,
        string lastMonth, string monthsAgo, string lastYear, string yearsAgo,
        string agesAgo, TimeSpan agesAgoThreshold)
    { ... }
}

මෙම FuzzyDateStringපන්ති අඩංගු:

public static class FuzzyDateExtensions
{
    public static string ToFuzzyDateString(this TimeSpan timespan)
    {
        return timespan.ToFuzzyDateString(new Grammar());
    }

    public static string ToFuzzyDateString(this TimeSpan timespan,
        Grammar grammar)
    {
        return GetFuzzyDateString(timespan, grammar);
    }

    public static string ToFuzzyDateString(this DateTime datetime)
    {
        return (DateTime.Now - datetime).ToFuzzyDateString();
    }

    public static string ToFuzzyDateString(this DateTime datetime,
       Grammar grammar)
    {
        return (DateTime.Now - datetime).ToFuzzyDateString(grammar);
    }


    private static string GetFuzzyDateString(TimeSpan timespan,
       Grammar grammar)
    {
        timespan = timespan.Duration();

        if (timespan >= grammar.AgesAgoThreshold)
        {
            return grammar.AgesAgo;
        }

        if (timespan < new TimeSpan(0, 2, 0))    // 2 minutes
        {
            return grammar.JustNow;
        }

        if (timespan < new TimeSpan(1, 0, 0))    // 1 hour
        {
            return String.Format(grammar.MinutesAgo, timespan.Minutes);
        }

        if (timespan < new TimeSpan(1, 55, 0))    // 1 hour 55 minutes
        {
            return grammar.OneHourAgo;
        }

        if (timespan < new TimeSpan(12, 0, 0)    // 12 hours
            && (DateTime.Now - timespan).IsToday())
        {
            return String.Format(grammar.HoursAgo, timespan.RoundedHours());
        }

        if ((DateTime.Now.AddDays(1) - timespan).IsToday())
        {
            return grammar.Yesterday;
        }

        if (timespan < new TimeSpan(32, 0, 0, 0)    // 32 days
            && (DateTime.Now - timespan).IsThisMonth())
        {
            return String.Format(grammar.DaysAgo, timespan.RoundedDays());
        }

        if ((DateTime.Now.AddMonths(1) - timespan).IsThisMonth())
        {
            return grammar.LastMonth;
        }

        if (timespan < new TimeSpan(365, 0, 0, 0, 0)    // 365 days
            && (DateTime.Now - timespan).IsThisYear())
        {
            return String.Format(grammar.MonthsAgo, timespan.RoundedMonths());
        }

        if ((DateTime.Now - timespan).AddYears(1).IsThisYear())
        {
            return grammar.LastYear;
        }

        return String.Format(grammar.YearsAgo, timespan.RoundedYears());
    }
}

මම සාක්ෂාත් කර ගැනීමට අවශ්ය මූලික දේවල් එක්, මෙන්ම දේශීයකරණ ලෙස, "අද" එකම අදහස් කරන බව "මෙම දින දර්ශනය දවස" බවයි, එසේ IsToday, IsThisMonth, IsThisYearක්රම මේ වගේ දෙස බලන්න:

public static bool IsToday(this DateTime date)
{
    return date.DayOfYear == DateTime.Now.DayOfYear && date.IsThisYear();
}

වටකුරු ක්‍රම මේ වගේ ය (මම ඊට ඇතුළත් කර ඇත RoundedMonths, එය ටිකක් වෙනස් ය):

public static int RoundedDays(this TimeSpan timespan)
{
    return (timespan.Hours > 12) ? timespan.Days + 1 : timespan.Days;
}

public static int RoundedMonths(this TimeSpan timespan)
{
    DateTime then = DateTime.Now - timespan;

    // Number of partial months elapsed since 1 Jan, AD 1 (DateTime.MinValue)
    int nowMonthYears = DateTime.Now.Year * 12 + DateTime.Now.Month;
    int thenMonthYears = then.Year * 12 + then.Month;                    

    return nowMonthYears - thenMonthYears;
}

මිනිසුන් මෙය ප්‍රයෝජනවත් සහ / හෝ රසවත් යැයි සිතමි: o)


17

PHP හි, මම එය කරන්නේ මේ ආකාරයට ය:

<?php
function timesince($original) {
    // array of time period chunks
    $chunks = array(
        array(60 * 60 * 24 * 365 , 'year'),
        array(60 * 60 * 24 * 30 , 'month'),
        array(60 * 60 * 24 * 7, 'week'),
        array(60 * 60 * 24 , 'day'),
        array(60 * 60 , 'hour'),
        array(60 , 'minute'),
    );

    $today = time(); /* Current unix time  */
    $since = $today - $original;

    if($since > 604800) {
    $print = date("M jS", $original);

    if($since > 31536000) {
        $print .= ", " . date("Y", $original);
    }

    return $print;
}

// $j saves performing the count function each time around the loop
for ($i = 0, $j = count($chunks); $i < $j; $i++) {

    $seconds = $chunks[$i][0];
    $name = $chunks[$i][1];

    // finding the biggest chunk (if the chunk fits, break)
    if (($count = floor($since / $seconds)) != 0) {
        break;
    }
}

$print = ($count == 1) ? '1 '.$name : "$count {$name}s";

return $print . " ago";

} ?>

5
ප්‍රශ්නය C # ටැග් කර ඇත. මෙම PHP කේතය ඇයි? IMHO, අදාළ වන්නේ C # කේතය පමණි
Kiquenet


14

පංති සහ බහුමාපකය භාවිතා කරමින් මම මෙය ලබා දෙන්නෙමි යැයි සිතුවෙමි. මා කලින් උපසිරැසි ගැන්වූ අතර එය උප-වර්ගීකරණය භාවිතා කළ අතර එය අවසන් වූයේ ඕනෑවට වඩා ඉහළින් ය. මම වඩාත් නම්‍යශීලී නියෝජිත / පොදු දේපල වස්තු ආකෘතියකට මාරු වී ඇති අතර එය සැලකිය යුතු ලෙස වඩා හොඳය. මගේ කේතය තරමක් නිවැරදි ය, ඕනෑවට වඩා සැලසුම් කර ඇති බවක් නොපෙනෙන "මාස ගණනාවකට පෙර" උත්පාදනය කිරීමට වඩා හොඳ ක්‍රමයක් මට ඉදිරිපත් කළ හැකි යැයි මම ප්‍රාර්ථනා කරමි.

මම හිතන්නේ මම තවමත් ජෙෆ්ගේ නම්-කඳුරැල්ල සමඟ බැඳී සිටින්නේ එය අඩු කේතයක් වන නිසාත් එය සරල නිසාත් ය (එය අපේක්ෂා කළ පරිදි ක්‍රියාත්මක වන බව සහතික කිරීම පහසුය).

පහත කේතය සඳහා PrintRelativeTime.GetRelativeTimeMessage (TimeSpan ago) සාපේක්ෂ කාල පණිවිඩය ලබා දෙයි (උදා: "ඊයේ").

public class RelativeTimeRange : IComparable
{
    public TimeSpan UpperBound { get; set; }

    public delegate string RelativeTimeTextDelegate(TimeSpan timeDelta);

    public RelativeTimeTextDelegate MessageCreator { get; set; }

    public int CompareTo(object obj)
    {
        if (!(obj is RelativeTimeRange))
        {
            return 1;
        }
        // note that this sorts in reverse order to the way you'd expect, 
        // this saves having to reverse a list later
        return (obj as RelativeTimeRange).UpperBound.CompareTo(UpperBound);
    }
}

public class PrintRelativeTime
{
    private static List<RelativeTimeRange> timeRanges;

    static PrintRelativeTime()
    {
        timeRanges = new List<RelativeTimeRange>{
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromSeconds(1),
                MessageCreator = (delta) => 
                { return "one second ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromSeconds(60),
                MessageCreator = (delta) => 
                { return delta.Seconds + " seconds ago"; }

            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromMinutes(2),
                MessageCreator = (delta) => 
                { return "one minute ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromMinutes(60),
                MessageCreator = (delta) => 
                { return delta.Minutes + " minutes ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromHours(2),
                MessageCreator = (delta) => 
                { return "one hour ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromHours(24),
                MessageCreator = (delta) => 
                { return delta.Hours + " hours ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromDays(2),
                MessageCreator = (delta) => 
                { return "yesterday"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-1)),
                MessageCreator = (delta) => 
                { return delta.Days + " days ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-2)),
                MessageCreator = (delta) => 
                { return "one month ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-1)),
                MessageCreator = (delta) => 
                { return (int)Math.Floor(delta.TotalDays / 30) + " months ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-2)),
                MessageCreator = (delta) => 
                { return "one year ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.MaxValue,
                MessageCreator = (delta) => 
                { return (int)Math.Floor(delta.TotalDays / 365.24D) + " years ago"; }
            }
        };

        timeRanges.Sort();
    }

    public static string GetRelativeTimeMessage(TimeSpan ago)
    {
        RelativeTimeRange postRelativeDateRange = timeRanges[0];

        foreach (var timeRange in timeRanges)
        {
            if (ago.CompareTo(timeRange.UpperBound) <= 0)
            {
                postRelativeDateRange = timeRange;
            }
        }

        return postRelativeDateRange.MessageCreator(ago);
    }
}

13
using System;
using System.Collections.Generic;
using System.Linq;

public static class RelativeDateHelper
{
    private static Dictionary<double, Func<double, string>> sm_Dict = null;

    private static Dictionary<double, Func<double, string>> DictionarySetup()
    {
        var dict = new Dictionary<double, Func<double, string>>();
        dict.Add(0.75, (mins) => "less than a minute");
        dict.Add(1.5, (mins) => "about a minute");
        dict.Add(45, (mins) => string.Format("{0} minutes", Math.Round(mins)));
        dict.Add(90, (mins) => "about an hour");
        dict.Add(1440, (mins) => string.Format("about {0} hours", Math.Round(Math.Abs(mins / 60)))); // 60 * 24
        dict.Add(2880, (mins) => "a day"); // 60 * 48
        dict.Add(43200, (mins) => string.Format("{0} days", Math.Floor(Math.Abs(mins / 1440)))); // 60 * 24 * 30
        dict.Add(86400, (mins) => "about a month"); // 60 * 24 * 60
        dict.Add(525600, (mins) => string.Format("{0} months", Math.Floor(Math.Abs(mins / 43200)))); // 60 * 24 * 365 
        dict.Add(1051200, (mins) => "about a year"); // 60 * 24 * 365 * 2
        dict.Add(double.MaxValue, (mins) => string.Format("{0} years", Math.Floor(Math.Abs(mins / 525600))));

        return dict;
    }

    public static string ToRelativeDate(this DateTime input)
    {
        TimeSpan oSpan = DateTime.Now.Subtract(input);
        double TotalMinutes = oSpan.TotalMinutes;
        string Suffix = " ago";

        if (TotalMinutes < 0.0)
        {
            TotalMinutes = Math.Abs(TotalMinutes);
            Suffix = " from now";
        }

        if (null == sm_Dict)
            sm_Dict = DictionarySetup();

        return sm_Dict.First(n => TotalMinutes < n.Key).Value.Invoke(TotalMinutes) + Suffix;
    }
}

මෙම ප්‍රශ්නයට තවත් පිළිතුරකට සමාන නමුත් ස්ථිතික ශබ්ද කෝෂයක් සහිත දිගු කිරීමේ ක්‍රමයක් ලෙස.


ශබ්ද කෝෂය ඔබව මෙහි මිලදී ගන්නේ කුමක් ද?
ස්ට්‍රිප්ලිං වෝරියර්

StriplingWarrior: ස්විච් ප්‍රකාශයකට සාපේක්ෂව කියවීමේ හා වෙනස් කිරීමේ පහසුව හෝ if / else ප්‍රකාශන තොගයක්. ශබ්ද කෝෂය ස්ථිතික වීම යනු අපට ToRelativeDate භාවිතා කිරීමට අවශ්‍ය සෑම අවස්ථාවකම එය සහ Func <,> වස්තු නිර්මාණය කළ යුතු නැත; එය නිර්මාණය කර ඇත්තේ එක් වරක් පමණි, මගේ පිළිතුරට මා සම්බන්ධ කළ ඒවාට සාපේක්ෂව.
ක්‍රිස් චරබාරුක්

මට පේනවා. Dictionary"අයිතම ආපසු ලබා දෙන අනුපිළිවෙල නිර්වචනය කර නැත" ( msdn.microsoft.com/en-us/library/xfhwa508.aspx ) පිළිබඳ ලියකියවිලි වල සඳහන් බැවින් මම සිතුවෙමි, සමහර විට එය භාවිතා කිරීමට හොඳම දත්ත ව්‍යුහය නොවේ දේවල් පිළිවෙලට තබා ගැනීම තරම් ඔබ බැලීමේ වේලාවන් ගැන තැකීමක් නොකරන විට.
ස්ට්‍රිප්ලිං වෝරියර්

StriplingWarrior: Dictionarys සමඟ භාවිතා කරන විට LINQ එය සැලකිල්ලට ගනී . ඔබ තවමත් එය සමඟ අපහසු නම්, ඔබට භාවිතා කළ හැකියSortedDictionary , නමුත් මගේම අත්දැකීම එය අනවශ්‍ය බව පෙන්නුම් කරයි.
ක්‍රිස් චරබාරුක්

12

ඔබ නරඹන්නාගේ කාල කලාපය දන්නා විට, දින දර්ශනයේ දින පරිමාණයෙන් භාවිතා කිරීම වඩාත් පැහැදිලි විය හැකිය. .NET පුස්තකාල ගැන මට හුරු නැති නිසා අවාසනාවකට ඔබ C # හි එය කරන්නේ කෙසේදැයි මම නොදනිමි.

පාරිභෝගික අඩවි වල, ඔබට මිනිත්තුවක් යටතේ අත් රැළි කළ හැකිය. "විනාඩියකටත් අඩු කාලයකට පෙර" හෝ "දැන්" ප්‍රමාණවත් තරම් හොඳ විය හැකිය.


11

ඔබට මෙය උත්සාහ කළ හැකිය. එය නිවැරදිව ක්‍රියා කරනු ඇතැයි මම සිතමි.

long delta = new Date().getTime() - date.getTime();
const int SECOND = 1;
const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;

if (delta < 0L)
{
  return "not yet";
}
if (delta < 1L * MINUTE)
{
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 2L * MINUTE)
{
  return "a minute ago";
}
if (delta < 45L * MINUTE)
{
  return ts.Minutes + " minutes ago";
}
if (delta < 90L * MINUTE)
{
  return "an hour ago";
}
if (delta < 24L * HOUR)
{
  return ts.Hours + " hours ago";
}
if (delta < 48L * HOUR)
{
  return "yesterday";
}
if (delta < 30L * DAY)
{
  return ts.Days + " days ago";
}
if (delta < 12L * MONTH)
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
  return years <= 1 ? "one year ago" : years + " years ago";
}

9

සේවාදායක පාර්ශවීය gwt භාවිතය සඳහා ජාවා:

import java.util.Date;

public class RelativeDateFormat {

 private static final long ONE_MINUTE = 60000L;
 private static final long ONE_HOUR = 3600000L;
 private static final long ONE_DAY = 86400000L;
 private static final long ONE_WEEK = 604800000L;

 public static String format(Date date) {

  long delta = new Date().getTime() - date.getTime();
  if (delta < 1L * ONE_MINUTE) {
   return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta)
     + " seconds ago";
  }
  if (delta < 2L * ONE_MINUTE) {
   return "one minute ago";
  }
  if (delta < 45L * ONE_MINUTE) {
   return toMinutes(delta) + " minutes ago";
  }
  if (delta < 90L * ONE_MINUTE) {
   return "one hour ago";
  }
  if (delta < 24L * ONE_HOUR) {
   return toHours(delta) + " hours ago";
  }
  if (delta < 48L * ONE_HOUR) {
   return "yesterday";
  }
  if (delta < 30L * ONE_DAY) {
   return toDays(delta) + " days ago";
  }
  if (delta < 12L * 4L * ONE_WEEK) {
   long months = toMonths(delta);
   return months <= 1 ? "one month ago" : months + " months ago";
  } else {
   long years = toYears(delta);
   return years <= 1 ? "one year ago" : years + " years ago";
  }
 }

 private static long toSeconds(long date) {
  return date / 1000L;
 }

 private static long toMinutes(long date) {
  return toSeconds(date) / 60L;
 }

 private static long toHours(long date) {
  return toMinutes(date) / 60L;
 }

 private static long toDays(long date) {
  return toHours(date) / 24L;
 }

 private static long toMonths(long date) {
  return toDays(date) / 30L;
 }

 private static long toYears(long date) {
  return toMonths(date) / 365L;
 }

}

ප්‍රශ්නය C # ටැග් කර ඇත. ඇයි මේ ජාවා කේතය ? IMHO, අදාළ වන්නේ C # කේතය පමණි
Kiquenet

9

E ජෙෆ්

var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks);

කෙසේ හෝ DateTimeප්‍රතිලාභ මත අඩු කිරීමක් කිරීම TimeSpan.

එබැවින් ඔබට කළ හැකිය

(DateTime.UtcNow - dt).TotalSeconds

නියතයන් අතින් ගුණ කිරීමත්, පසුව ගුණ කිරීම සමඟ අදහස් දැක්වීමත් පුදුමයට කරුණකි. එය කිසියම් නොමඟ ගිය ප්‍රශස්තිකරණයක්ද?


8

මෙන්න ඇල්ගොරිතම ස්ටැක් ඕවර් ප්‍රවාහය භාවිතා කරන නමුත් දෝෂ නිරාකරණයකින් ව්‍යාජ කේතයේ වඩාත් සංක්ෂිප්තව නැවත ලියා ඇත ("පැයකට පෙර" නැත). ශ්‍රිතය තත්පර ගණනකට පෙර (ධනාත්මක) කාලයක් ගත වන අතර "පැය 3 කට පෙර" හෝ "ඊයේ" වැනි මානව හිතකාමී නූලක් ලබා දෙයි.

agoify($delta)
  local($y, $mo, $d, $h, $m, $s);
  $s = floor($delta);
  if($s<=1)            return "a second ago";
  if($s<60)            return "$s seconds ago";
  $m = floor($s/60);
  if($m==1)            return "a minute ago";
  if($m<45)            return "$m minutes ago";
  $h = floor($m/60);
  if($h==1)            return "an hour ago";
  if($h<24)            return "$h hours ago";
  $d = floor($h/24);
  if($d<2)             return "yesterday";
  if($d<30)            return "$d days ago";
  $mo = floor($d/30);
  if($mo<=1)           return "a month ago";
  $y = floor($mo/12);
  if($y<1)             return "$mo months ago";
  if($y==1)            return "a year ago";
  return "$y years ago";

8

මෙම තාර්කික සේවාදායක පාර්ශවය සිදු කිරීමෙන් ඔබට සේවාදායක පාර්ශවීය බර අඩු කර ගත හැකිය. යොමු කිරීම සඳහා සමහර ඩිග් පිටුවල මූලාශ්‍රය බලන්න. ජාවාස්ක්‍රිප්ට් මඟින් සැකසෙන යුග කාල අගයක් විමෝචනය කිරීමට ඔවුන් සතුව ඇත. මේ ආකාරයෙන් ඔබට අවසාන පරිශීලකයාගේ කාල කලාපය කළමනාකරණය කිරීමට අවශ්‍ය නොවේ. නව සේවාදායක පැත්තේ කේතය මෙවැනි දෙයක් වනු ඇත:

public string GetRelativeTime(DateTime timeStamp)
{
    return string.Format("<script>printdate({0});</script>", timeStamp.ToFileTimeUtc());
}

ඔබට එහි NOSCRIPT වාරණයක් එකතු කර ToString () සිදු කළ හැකිය.


8

මට මෙම පිළිතුර ලැබුනේ බිල් ගේට්ස්ගේ එක් බ්ලොග් අඩවියෙනි. මට එය මගේ බ්‍රව්සර ඉතිහාසයේ සොයා ගැනීමට අවශ්‍ය වන අතර මම ඔබට සබැඳිය ලබා දෙමි.

එකම දේ කිරීමට ජාවාස්ක්‍රිප්ට් කේතය (ඉල්ලූ පරිදි):

function posted(t) {
    var now = new Date();
    var diff = parseInt((now.getTime() - Date.parse(t)) / 1000);
    if (diff < 60) { return 'less than a minute ago'; }
    else if (diff < 120) { return 'about a minute ago'; }
    else if (diff < (2700)) { return (parseInt(diff / 60)).toString() + ' minutes ago'; }
    else if (diff < (5400)) { return 'about an hour ago'; }
    else if (diff < (86400)) { return 'about ' + (parseInt(diff / 3600)).toString() + ' hours ago'; }
    else if (diff < (172800)) { return '1 day ago'; } 
    else {return (parseInt(diff / 86400)).toString() + ' days ago'; }
}

මූලික වශයෙන්, ඔබ වැඩ කරන්නේ තත්පරයට අනුව ය.


8

ඔබට පහත පරිදි TimeAgo දිගුව භාවිතා කළ හැකිය :

public static string TimeAgo(this DateTime dateTime)
{
    string result = string.Empty;
    var timeSpan = DateTime.Now.Subtract(dateTime);
 
    if (timeSpan <= TimeSpan.FromSeconds(60))
    {
        result = string.Format("{0} seconds ago", timeSpan.Seconds);
    }
    else if (timeSpan <= TimeSpan.FromMinutes(60))
    {
        result = timeSpan.Minutes > 1 ? 
            String.Format("about {0} minutes ago", timeSpan.Minutes) :
            "about a minute ago";
    }
    else if (timeSpan <= TimeSpan.FromHours(24))
    {
        result = timeSpan.Hours > 1 ? 
            String.Format("about {0} hours ago", timeSpan.Hours) : 
            "about an hour ago";
    }
    else if (timeSpan <= TimeSpan.FromDays(30))
    {
        result = timeSpan.Days > 1 ? 
            String.Format("about {0} days ago", timeSpan.Days) : 
            "yesterday";
    }
    else if (timeSpan <= TimeSpan.FromDays(365))
    {
        result = timeSpan.Days > 30 ? 
            String.Format("about {0} months ago", timeSpan.Days / 30) : 
            "about a month ago";
    }
    else
    {
        result = timeSpan.Days > 365 ? 
            String.Format("about {0} years ago", timeSpan.Days / 365) : 
            "about a year ago";
    }
 
    return result;
}

හෝ ටයිමගෝ වෙතින් රේසර් දිගුව සමඟ jQuery ප්ලගිනය භාවිතා කරන්න .


6

මෙම ලිපියට අදාළ පිළිතුරු දැනටමත් ඇති බව මම සිතමි, නමුත් කෙනෙකුට මෙය භාවිතා කළ හැකි අතර එය ප්ලගිනය මෙන් භාවිතා කිරීමට පහසු වන අතර ක්‍රමලේඛකයන්ට පහසුවෙන් කියවිය හැකිය. ඔබේ නිශ්චිත දිනය යවන්න, එහි වටිනාකම නූල් ආකාරයෙන් ලබා ගන්න:

public string RelativeDateTimeCount(DateTime inputDateTime)
{
    string outputDateTime = string.Empty;
    TimeSpan ts = DateTime.Now - inputDateTime;

    if (ts.Days > 7)
    { outputDateTime = inputDateTime.ToString("MMMM d, yyyy"); }

    else if (ts.Days > 0)
    {
        outputDateTime = ts.Days == 1 ? ("about 1 Day ago") : ("about " + ts.Days.ToString() + " Days ago");
    }
    else if (ts.Hours > 0)
    {
        outputDateTime = ts.Hours == 1 ? ("an hour ago") : (ts.Hours.ToString() + " hours ago");
    }
    else if (ts.Minutes > 0)
    {
        outputDateTime = ts.Minutes == 1 ? ("1 minute ago") : (ts.Minutes.ToString() + " minutes ago");
    }
    else outputDateTime = "few seconds ago";

    return outputDateTime;
}

5
/** 
 * {@code date1} has to be earlier than {@code date2}.
 */
public static String relativize(Date date1, Date date2) {
    assert date2.getTime() >= date1.getTime();

    long duration = date2.getTime() - date1.getTime();
    long converted;

    if ((converted = TimeUnit.MILLISECONDS.toDays(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "day" : "days");
    } else if ((converted = TimeUnit.MILLISECONDS.toHours(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "hour" : "hours");
    } else if ((converted = TimeUnit.MILLISECONDS.toMinutes(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "minute" : "minutes");
    } else if ((converted = TimeUnit.MILLISECONDS.toSeconds(duration)) > 0) {
        return String.format("%d %s ago", converted, converted == 1 ? "second" : "seconds");
    } else {
        return "just now";
    }
}

5

ඔබට වැනි ප්‍රතිදානයක් ලබා ගැනීමට අවශ්‍ය නම් "2 days, 4 hours and 12 minutes ago", ඔබට කාල පරාසයක් අවශ්‍ය වේ:

TimeSpan timeDiff = DateTime.Now-CreatedDate;

එවිට ඔබට කැමති අගයන්ට ප්‍රවේශ විය හැකිය:

timeDiff.Days
timeDiff.Hours

etc ...


4

මම මේ සඳහා පහසු දිගු ක්‍රම කිහිපයක් ලබා දී කේතය වඩාත් කියවිය හැකි කරමි. පළමුව, සඳහා දිගු කිරීමේ ක්‍රම කිහිපයක් Int32.

public static class TimeSpanExtensions {

    public static TimeSpan Days(this int value) {

        return new TimeSpan(value, 0, 0, 0);
    }

    public static TimeSpan Hours(this int value) {

        return new TimeSpan(0, value, 0, 0);
    }

    public static TimeSpan Minutes(this int value) {

        return new TimeSpan(0, 0, value, 0);
    }

    public static TimeSpan Seconds(this int value) {

        return new TimeSpan(0, 0, 0, value);
    }

    public static TimeSpan Milliseconds(this int value) {

        return new TimeSpan(0, 0, 0, 0, value);
    }

    public static DateTime Ago(this TimeSpan value) {

        return DateTime.Now - value;
    }
}

එහෙනම් එකක් DateTime.

public static class DateTimeExtensions {

    public static DateTime Ago(this DateTime dateTime, TimeSpan delta) {

        return dateTime - delta;
    }
}

දැන්, ඔබට පහත වැනි දෙයක් කළ හැකිය:

var date = DateTime.Now;
date.Ago(2.Days()); // 2 days ago
date.Ago(7.Hours()); // 7 hours ago
date.Ago(567.Milliseconds()); // 567 milliseconds ago
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.