Top datetime Questions

List of Tags
717
J. Pablo Fernández

How can I get a timestamp in JavaScript?

Something similar to Unix's timestamp, that is, a single number that represents the current time and date. Either as a number or a string.

Answered By: daveb ( 886)

The following returns the number of milliseconds since the epoch.

new Date().getTime();

I am hoping to make this question and the answers to it the definitive guide to dealing with daylight saving time, in particular for dealing with the actual change overs.

If you have anything to add, please do

Many systems are dependent on keeping accurate time, the problem is with changes to time due to daylight savings - moving the clock forward or backwards.

For instance, one has business rules in an order taking system that depend on the time of the order - if the clock changes, the rules might not be as clear. How should the time of the order be persisted? There is of course an endless number of scenarios - this one is simply an illustrative one.

  • How have you dealt with the daylight saving issue?
  • What assumptions are part of your solution? (looking for context here)

As important, if not more so:

  • What did you try that did not work?
  • Why did it not work?

I would be interested in programming, OS, data persistence and other pertinent aspects of the issue.

General answers are great, but I would also like to see details especially if they are only available on one platform.


Summary of answers and other data: (please add yours)

Do:

  • Whenever you are referring to a particular moment in time, persist the time according to a unified standard that is not affected by daylight savings. GMT and UTC have been mentioned by different people, though UTC seems to be mentioned most often.
  • Include the local time offset as is (including DST offset) when storing timestamps.
  • Include the original timezone name, so you can reconstruct the original time at a later point and display correct offsets if needed.
  • Remember that DST offsets are not always an integer number of hours (e.g. Indian Standard Time is UTC+05:30).
  • If using Java, use JodaTime. - http://joda-time.sourceforge.net/
  • If using .Net, consider using NodaTime. - http://code.google.com/p/noda-time/
  • If using PHP > 5.2, use the native time zones conversions provided by DateTime, and DateTimeZone classes. To keep PHP with up to date Olson data install periodically this PECL package. See answer
  • Create a table TZOffsets with three columns: RegionClassId, StartDateTime, and OffsetMinutes (int, in minutes). See answer
  • Business rules should always work on civil time (UTC/GMT).
  • Internally, keep timestamps in something like civil-time-seconds-from-epoch. See answer.
  • Only convert to local times at the last possible moment.
  • Remember that timezones and offsets are not fixed and may change. For instance, historically US and UK used the same dates to 'spring forward' and 'fall back'. However in the mid 2000's the US changed the dates that the clocks get changed on. This now means that for 48 weeks of the year the difference between London time and New York time is 5 hours and for 4 weeks (3 in the spring, 1 in the autumn) it is 4 hours. Be aware of items like this in any calculations that involve multiple zones.
  • Consider the type of time (actual event time, broadcast time, relative time, historical time, recurring time) what elements (timestamp, timezone offset and timezone name) you need to store for correct retrieval - see "Types of Time" in answer.
  • Check if your DBMS needs to be shutdown during transition.
  • Keep your OS, database and application tzdata files in sync, between themselves and the rest of the world.
  • On Servers, set hardware clocks and OS clocks to UTC.
  • Use NTP services on all servers.
  • Store server time, not client time.
  • If doing historical auditing store both UTC and local time (this allows exact pinpointing of time, as conversion tables will change).
  • If using FAT32, remember that timestamps are stored in local time, not UTC.
  • When dealing with recurring events (weekly TV show, for example), remember that the time changes with DST and will be different across time zones.

Don't:

  • Do not use javascript date and time calculations in web apps unless you ABSOLUTELY have to.
  • Never trust client datetime. It may very well be incorrect.
  • Do not compare client datetimes with server datetimes.

Testing:

  • When testing make sure you test countries in the Western and Eastern hemispheres, with both DST in progress and not and a country that does not use DST (6 in total).
  • Test all third party libraries and applications and make sure they handle timezone data correctly.

Reference:

Other:

  • Lobby your representative to end the abomination that is DST. We can always hope...
  • Lobby for EST
Answered By: Yuval Adam ( 149)

Always persist the time according to a unified standard, preferably UTC.

UTC is agnostic to daylight saving time and as such it is a good baseline. Once you have that, displaying the proper time according to time zone, DST, etc... is just a matter of applying the proper delta.

Persist globally, display locally. - Me, Now

555
m_oLogin

What would you recommend using between a datetime and a timestamp field, and why? (using mysql). I'm working with php on the server side.

Answered By: blivet ( 382)

Timestamps in MySQL generally used to track changes to records, and are often updated every time the record is changed. If you want to store a specific value you should use a datetime field.

If you meant that you want to decide between using a UNIX timestamp or a native MySQL datetime field, go with the native format. You can do calculations within MySQL that way ("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)") and it is simple to change the format of the value to a UNIX timestamp ("SELECT UNIX_TIMESTAMP(my_datetime)") when you query the record if you want to operate on it with PHP.

542
Jeff Atwood

Given a specific DateTime value, how do I display relative time, like

  • 2 hours ago
  • 3 days ago
  • a month ago

a la Ruby on Rail's time ago in words helper.

Answered By: Vincent Robert ( 396)

Jeff, your code is nice but could be clearer with constants (as suggested in Code Complete).

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 < 0)
{
  return "not yet";
}
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";
}
481
Jeff Atwood

Given a DateTime representing a person's birthday, how do I calculate their age?

Answered By: Mike Polen ( 511)

For some reason Jeff's code didn't seem simple enough. To me this seems simpler and easier to understand:

DateTime today = DateTime.Today;
int age = today.Year - bday.Year;
if (bday > today.AddYears(-age)) age--;
315
Naga Kiran

I noticed that JavaScript's new Date() function is very smart in accepting dates in several formats.

Xmas95 = new Date("25 Dec, 1995 23:15:00")
Xmas95 = new Date("2009 06 12,12:52:39")
Xmas95 = new Date("20 09 2006,12:52:39")

I could not find documentation anywhere showing all the valid string formats while calling new Date() function.

This is for converting a string to date. If we look at the opposite side that is converting date object to string, until now I was under the impression that JavaScript doesn't have a built-in API to format a date object into a string.

Editor's note: The following approach is the asker's attempt that worked on a particular browser but does not work in general; see the answers on this page to see some actual solutions.

Today, I played with the toString() method on the date object and surprisingly it serves the purpose of formatting date to strings.

var d1=new Date();
d1.toString('yyyy-MM-dd');       //returns "2009-06-29"
d1.toString('dddd, MMMM ,yyyy')  //returns "Monday, June 29,2009"

Also here I couldn't find any documentation on all the ways we can format the date object into a string.

Where is the documentation which lists the format specifiers supported by the Date() object?

Answered By: Haim Evgi ( 313)

I love 10 ways to format time and date using JavaScript and Working with Dates.

Basically, you have three methods and you have to combine the strings for yourself:

getDate(): Returns the date
getMonth(): Returns the month
getFullYear(): Returns the year

Example:

<script type="text/javascript">
    var d = new Date();
    var curr_date = d.getDate();
    var curr_month = d.getMonth() + 1; //Months are zero based
    var curr_year = d.getFullYear();
    document.write(curr_date + "-" + curr_month + "-" + curr_year);
</script>
219
David Basarab

I need to find a bottleneck and need to accurately as possible measure time.

Is the following code snippet the best way to measure the performance?

DateTime startTime = DateTime.Now;

// Some execution process

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
Answered By: Markus Olsson ( 334)

No, it's not. Use the Stopwatch (in System.Diagnostics)

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

Stopwatch automatically checks for the existence of high-precision timers.

It is worth mentioning that DateTime.Now often is quite a bit slower than DateTime.UtcNow due to the work that has to be done with timezones, DST and such.

DateTime.UtcNow typically has a resolution of 15 ms. See John Chapman's blog post about DateTime.Now precision for a great summary.

Interesting trivia: The stopwatch falls back on DateTime.UtcNow if your hardware doesn't support a high frequency counter. You can check to see if Stopwatch uses hardware to achieve high precision by looking at the static field Stopwatch.IsHighResolution.

172
gnanesh

I have two dates of the form:

Start Date: 2007-03-24 
End Date: 2009-06-26

Now I need to find the difference between these two in the following form:

2 years, 3 months and 2 days

How can I do this in PHP?

Answered By: Emil H ( 186)

You can use strtotime() to convert two dates to unix time and then calculate the number of seconds between them. From this it's rather easy to calculate different time periods.

$date1 = "2007-03-24";
$date2 = "2009-06-26";

$diff = abs(strtotime($date2) - strtotime($date1));

$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

printf("%d years, %d months, %d days\n", $years, $months, $days);

Edit: Obviously the preferred way of doing this is like described by jurka below. My code is generally only recommended if you don't have PHP 5.3 or better.

Several people in the comments have pointed out that the code above is only an approximation. I still believe that for most purposes that's fine, since the usage of a range is more to provide a sense of how much time has passed or remains rather than to provide precision - if you want to do that, just output the date.

Despite all that, I've decided to address the complaints. If you truly need an exact range but haven't got access to PHP 5.3, use the code below (it should work in PHP 4 as well). This is a direct port of the code that PHP uses internally to calculate ranges, with the exception that it doesn't take daylight savings time into account. That means that it's off by an hour at most, but except for that it should be correct.

<?php

/**
 * Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff()
 * implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved.
 * 
 * See here for original code:
 * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup
 * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup
 */

function _date_range_limit($start, $end, $adj, $a, $b, $result)
{
    if ($result[$a] < $start) {
        $result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1;
        $result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1);
    }

    if ($result[$a] >= $end) {
        $result[$b] += intval($result[$a] / $adj);
        $result[$a] -= $adj * intval($result[$a] / $adj);
    }

    return $result;
}

function _date_range_limit_days($base, $result)
{
    $days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    $days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    _date_range_limit(1, 13, 12, "m", "y", &$base);

    $year = $base["y"];
    $month = $base["m"];

    if (!$result["invert"]) {
        while ($result["d"] < 0) {
            $month--;
            if ($month < 1) {
                $month += 12;
                $year--;
            }

            $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
            $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];

            $result["d"] += $days;
            $result["m"]--;
        }
    } else {
        while ($result["d"] < 0) {
            $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
            $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];

            $result["d"] += $days;
            $result["m"]--;

            $month++;
            if ($month > 12) {
                $month -= 12;
                $year++;
            }
        }
    }

    return $result;
}

function _date_normalize($base, $result)
{
    $result = _date_range_limit(0, 60, 60, "s", "i", $result);
    $result = _date_range_limit(0, 60, 60, "i", "h", $result);
    $result = _date_range_limit(0, 24, 24, "h", "d", $result);
    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    $result = _date_range_limit_days(&$base, &$result);

    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    return $result;
}

/**
 * Accepts two unix timestamps.
 */
function _date_diff($one, $two)
{
    $invert = false;
    if ($one > $two) {
        list($one, $two) = array($two, $one);
        $invert = true;
    }

    $key = array("y", "m", "d", "h", "i", "s");
    $a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
    $b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));

    $result = array();
    $result["y"] = $b["y"] - $a["y"];
    $result["m"] = $b["m"] - $a["m"];
    $result["d"] = $b["d"] - $a["d"];
    $result["h"] = $b["h"] - $a["h"];
    $result["i"] = $b["i"] - $a["i"];
    $result["s"] = $b["s"] - $a["s"];
    $result["invert"] = $invert ? 1 : 0;
    $result["days"] = intval(abs(($one - $two)/86400));

    if ($invert) {
        _date_normalize(&$a, &$result);
    } else {
        _date_normalize(&$b, &$result);
    }

    return $result;
}

$date = "1986-11-10 19:37:22";

print_r(_date_diff(strtotime($date), time()));
print_r(_date_diff(time(), strtotime($date)));

Given two date ranges, what is the simplest or most efficient way to determine whether the two date ranges overlap?

As an example, suppose we have ranges denoted by DateTime variables StartDate1 to EndDate1 and StartDate2 to EndDate2.

Answered By: Charles Bretana ( 312)

Let ConditionA Mean DateRange A Completely After DateRange B (True if StartA > EndB)

Let ConditionB Mean DateRange A Completely Before DateRange B (True if EndA < StartB)

Then Overlap exists if Neither A Nor B is true ( If one range is neither completely after the other, nor completely before the other, then they must overlap)

Now deMorgan's law says that:

Not (A Or B) <=> Not A And Not B

Which means (StartA <= EndB) and (EndA >= StartB)

NOTE: This includes conditions where the edges overlap exactly. If you wish to exclude that, change the >= operators to >, and <= to <

168
Off Rhoden

I have to create an "Expires" value 5 minutes in the future, but I have to supply it in UNIX Timestamp format. I have this so far, but it seems like a hack.

def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    epoch = datetime.datetime(1970, 1, 1)
    seconds_in_a_day = 60 * 60 * 24
    five_minutes = datetime.timedelta(seconds=5*60)
    five_minutes_from_now = datetime.datetime.now() + five_minutes
    since_epoch = five_minutes_from_now - epoch
    return since_epoch.days * seconds_in_a_day + since_epoch.seconds

Is there a module or function that does the timestamp conversion for me?

Answered By: Cat Plus Plus ( 227)

Another way is to use time.mktime:

future = datetime.datetime.now() + datetime.timedelta(minutes=5)
return time.mktime(future.timetuple())

It's also more portable than %s flag to strftime — latter is not supported on win32.