2013-05-16 74 views
1

Я пытался найти ответ, но я не смог найти его. Я пытаюсь создать функцию JavaScript, которая принимает две даты и возвращает строку в формате «x years, y months, z days, hours, b minutes, c seconds». Обычное повторное разделение не работает, потому что месяцы могут иметь разное количество дней. Я нашел несколько источников, но они либо идут только до дней/часов/минут, опуская месячную проблему, либо просто ошибочно усредняют дни месяца.JavaScript год, месяц, день, час, минута, вторая разница

function dateDifference(date) { 
    now = new Date(); 
    ??; 
    return difference; //returns something like "x years, y months, z days, a hours, b minutes, c seconds" 
} 

Спасибо за помощь

+0

Когда вы говорите «берет две даты и возвращает строку», что именно вы возвращаетесь? Вы ищете разницу между двумя датами? – sbatson5

+0

да, я в основном ищу разницу между двумя датами (или датой и сейчас). Я могу сделать окончательный формат строки самостоятельно. Это те числовые значения, с которыми я столкнулся. – JonnyRobbie

+0

Когда я вычитаю даты, разве я не получу разницу в миллисекундах? Я хотел бы преобразовать это в yy, mm, dd, hh, mm, ss, и эти месяцы проблематичны. – JonnyRobbie

ответ

2

Используйте moment.js, который является действительно хорошей функцией, и вы можете иметь время вернулось в простом текстовом виде.

http://momentjs.com/

Прочитайте документацию по API и с некоторым умным хакерством на функции, вы можете получить требуемый формат вывод строки. И, кстати, нет конкретной библиотеки, которая может выдавать даты в вашем требуемом формате, о котором я знаю. Итак, дайте мне знать, если вы где-то и нужна помощь moment.js

+0

Я могу легко отформатировать возвращаемую строку. Мне просто нужны точные численные значения. Что касается внешнего API, я боюсь использовать это, так как я могу назвать эту функцию десятками раз (может быть, даже сто раз) на страницу, и я боюсь значительного замедления. – JonnyRobbie

+0

Как и ответ @ Salem, вы можете написать свой собственный ассоциативный объект, который отображает текущий месяц на количество дней, а затем вам нужно принимать крайние случаи, такие как високосные годы и прочее. Или самый простой способ - использовать только функции, которые вы хотите от moment.js. Я попытаюсь посмотреть, смогу ли я написать демоверсию. – theshadowmonkey

0

Вы можете просто вычитать две даты, чтобы получить миллисекунды, а затем работать оттуда:

var date1 = new Date("2012/06/12 12:00:30"); 
var date2 = new Date("2013/06/15 12:00:40"); 
var diff = Math.abs(date2 - date1); 
var years = Math.floor(diff/(1000*60*60*24*365)); // 1 
var months = Math.floor((diff - years)/(1000*60*60*24*30)) % 12; // 0 
(...) 
+0

Проблема, с которой вы сталкиваетесь, заключается в том, что не каждый месяц имеет такое же количество дней. – sbatson5

+0

Но есть точно проблема, которую я описал. В месяцах не все имеют одинаковое количество дней. – JonnyRobbie

+0

@MarekD Но как вы можете вернуть «х месяцев разницы», если месяц не постоянный? Например, сколько месяцев составляет от 28/2 до 29/3 (в том же году)? А с 28/2 до 2/3? – Salem

2

Использование .getTime для преобразования даты в миллисекундах:

var date1 = new Date(), 
    date2 = new Date(someDate), 
    diff = Math.abs(date1.getTime() - date2.getTime()); 

// then convert into years, months, etc 

EDIT: Вы не можете уйти от усреднения длины месяцев как проблема часто будет неоднозначным. например, если подсчет разницы между 3 февраля и 10 марта составляет 1 месяц и 7 дней (если месяц составляет 28 дней, как в феврале) или 1 месяц и 4 дня (если месяц составляет 31 день, как в марте)?

EDIT2: исправлена ​​моя истинно ужасная математика.

EDIT3: На самом деле, думая об этом, любой нормальный человек переносит день с первого месяца на последний месяц и использует его для расчета разницы в днях. Итак:

var date1 = new Date(), 
    date2 = new Date(1981, 10, 18); 
    switch = (date2.getTime() - date1.getTime()) < 0 ? false : true, // work out which is the later date 
    laterDate = switch ? date2 : date1; 
    earlierDate = switch ? date1 : date2; 
    dayDiff = laterDate.getDate() - earlierDate.getDate(), 
    monthDiff = laterDate.getMonth() - earlierDate.getMonth(), // javascript uses zero-indexed months (0-11 rather than the more conventional 1-12) 
    yearDiff = laterDate.getFullYear() - earlierDate.getFullYear(), 
    months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 

if (dayDiff < 0) { 
    monthDiff--; 
    dayDiff += months[laterDate.getMonth()-1]; // -1 because we want the previous month 
} 

if (monthDiff < 0) { 
    yearDiff--; 
    monthDiff += 12; 
} 

console.log(yearDiff+' years, '+monthDiff+' months, '+dayDiff+' days'); 

Я думаю, что это заставляет нас большую часть пути там, но мы все еще должны рассмотреть високосные

EDIT 4: Исправлена ​​пара (иногда, но, к сожалению, не всегда стирает) от по 1 ошибкам

+0

такая же проблема как с другим ответом. В месяцах не все имеют одинаковое количество дней. В этом суть моей проблемы, почему я не могу просто использовать деление, не так ли? – JonnyRobbie

+0

+1 Я думаю, что ваше редактирование действительно отвечает на вопрос. – Salem

+0

Спасибо RobJ за ваш код .... Я думаю, что это так близко, как только он становится без осложнений для високосных лет. Спасибо – JonnyRobbie

Смежные вопросы