var clockedIn = "2017-03-02 09:45:25";
var clockedOut = "2017-03-04 09:49:06";
//sets timestamps to vars
var now = clockedIn;
var then = clockedOut;
var diff = moment.duration(moment(then).diff(moment(now)));
console.log(diff.format("d [days], H [hours], m [minutes] [and] s [seconds] "));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>
<script>
/*! Moment Duration Format v1.3.0
* https://github.com/jsmreese/moment-duration-format
* Date: 2014-07-15
*
* Duration format plugin function for the Moment.js library
* http://momentjs.com/
*
* Copyright 2014 John Madhavan-Reese
* Released under the MIT license
*/
(function (root, undefined) {
\t // repeatZero(qty)
\t // returns "0" repeated qty times
\t function repeatZero(qty) {
\t \t var result = "";
\t \t
\t \t // exit early
\t \t // if qty is 0 or a negative number
\t \t // or doesn't coerce to an integer
\t \t qty = parseInt(qty, 10);
\t \t if (!qty || qty < 1) { return result; }
\t \t
\t \t while (qty) {
\t \t \t result += "0";
\t \t \t qty -= 1;
\t \t }
\t \t
\t \t return result;
\t }
\t
\t // padZero(str, len [, isRight])
\t // pads a string with zeros up to a specified length
\t // will not pad a string if its length is aready
\t // greater than or equal to the specified length
\t // default output pads with zeros on the left
\t // set isRight to `true` to pad with zeros on the right
\t function padZero(str, len, isRight) {
\t \t if (str == null) { str = ""; }
\t \t str = "" + str;
\t \t
\t \t return (isRight ? str : "") + repeatZero(len - str.length) + (isRight ? "" : str);
\t }
\t
\t // isArray
\t function isArray(array) {
\t \t return Object.prototype.toString.call(array) === "[object Array]";
\t }
\t
\t // isObject
\t function isObject(obj) {
\t \t return Object.prototype.toString.call(obj) === "[object Object]";
\t }
\t
\t // findLast
\t function findLast(array, callback) {
\t \t var index = array.length;
\t \t while (index -= 1) {
\t \t \t if (callback(array[index])) { return array[index]; }
\t \t }
\t }
\t // find
\t function find(array, callback) {
\t \t var index = 0,
\t \t \t max = array.length,
\t \t \t match;
\t \t \t
\t \t if (typeof callback !== "function") {
\t \t \t match = callback;
\t \t \t callback = function (item) {
\t \t \t \t return item === match;
\t \t \t };
\t \t }
\t \t while (index < max) {
\t \t \t if (callback(array[index])) { return array[index]; }
\t \t \t index += 1;
\t \t }
\t }
\t
\t // each
\t function each(array, callback) {
\t \t var index = 0,
\t \t \t max = array.length;
\t \t \t
\t \t if (!array || !max) { return; }
\t \t while (index < max) {
\t \t \t if (callback(array[index], index) === false) { return; }
\t \t \t index += 1;
\t \t }
\t }
\t
\t // map
\t function map(array, callback) {
\t \t var index = 0,
\t \t \t max = array.length,
\t \t \t ret = [];
\t \t if (!array || !max) { return ret; }
\t \t \t \t
\t \t while (index < max) {
\t \t \t ret[index] = callback(array[index], index);
\t \t \t index += 1;
\t \t }
\t \t
\t \t return ret;
\t }
\t
\t // pluck
\t function pluck(array, prop) {
\t \t return map(array, function (item) {
\t \t \t return item[prop];
\t \t });
\t }
\t
\t // compact
\t function compact(array) {
\t \t var ret = [];
\t \t
\t \t each(array, function (item) {
\t \t \t if (item) { ret.push(item); }
\t \t });
\t \t
\t \t return ret;
\t }
\t
\t // unique
\t function unique(array) {
\t \t var ret = [];
\t \t
\t \t each(array, function (_a) {
\t \t \t if (!find(ret, _a)) { ret.push(_a); }
\t \t });
\t \t
\t \t return ret;
\t }
\t
\t // intersection
\t function intersection(a, b) {
\t \t var ret = [];
\t \t
\t \t each(a, function (_a) {
\t \t \t each(b, function (_b) {
\t \t \t \t if (_a === _b) { ret.push(_a); }
\t \t \t });
\t \t });
\t \t
\t \t return unique(ret);
\t }
\t
\t // rest
\t function rest(array, callback) {
\t \t var ret = [];
\t \t
\t \t each(array, function (item, index) {
\t \t \t if (!callback(item)) {
\t \t \t \t ret = array.slice(index);
\t \t \t \t return false;
\t \t \t }
\t \t });
\t \t
\t \t return ret;
\t }
\t // initial
\t function initial(array, callback) {
\t \t var reversed = array.slice().reverse();
\t \t
\t \t return rest(reversed, callback).reverse();
\t }
\t
\t // extend
\t function extend(a, b) {
\t \t for (var key in b) {
\t \t \t if (b.hasOwnProperty(key)) { a[key] = b[key]; }
\t \t }
\t \t
\t \t return a;
\t }
\t \t \t
\t // define internal moment reference
\t var moment;
\t if (typeof require === "function") {
\t \t try { moment = require('moment'); }
\t \t catch (e) {}
\t }
\t
\t if (!moment && root.moment) {
\t \t moment = root.moment;
\t }
\t
\t if (!moment) {
\t \t throw "Moment Duration Format cannot find Moment.js";
\t }
\t
\t // moment.duration.format([template] [, precision] [, settings])
\t moment.duration.fn.format = function() {
\t \t var tokenizer, tokens, types, typeMap, momentTypes, foundFirst, trimIndex,
\t \t \t args = [].slice.call(arguments),
\t \t \t settings = extend({}, this.format.defaults),
\t \t \t // keep a shadow copy of this moment for calculating remainders
\t \t \t remainder = moment.duration(this);
\t \t // add a reference to this duration object to the settings for use
\t \t // in a template function
\t \t settings.duration = this;
\t \t // parse arguments
\t \t each(args, function (arg) {
\t \t \t if (typeof arg === "string" || typeof arg === "function") {
\t \t \t \t settings.template = arg;
\t \t \t \t return;
\t \t \t }
\t \t \t if (typeof arg === "number") {
\t \t \t \t settings.precision = arg;
\t \t \t \t return;
\t \t \t }
\t \t \t if (isObject(arg)) {
\t \t \t \t extend(settings, arg);
\t \t \t }
\t \t });
\t \t // types
\t \t types = settings.types = (isArray(settings.types) ? settings.types : settings.types.split(" "));
\t \t // template
\t \t if (typeof settings.template === "function") {
\t \t \t settings.template = settings.template.apply(settings);
\t \t }
\t \t // tokenizer regexp
\t \t tokenizer = new RegExp(map(types, function (type) {
\t \t \t return settings[type].source;
\t \t }).join("|"), "g");
\t \t // token type map function
\t \t typeMap = function (token) {
\t \t \t return find(types, function (type) {
\t \t \t \t return settings[type].test(token);
\t \t \t });
\t \t };
\t \t // tokens array
\t \t tokens = map(settings.template.match(tokenizer), function (token, index) {
\t \t \t var type = typeMap(token),
\t \t \t \t length = token.length;
\t \t \t return {
\t \t \t \t index: index,
\t \t \t \t length: length,
\t \t \t \t // replace escaped tokens with the non-escaped token text
\t \t \t \t token: (type === "escape" ? token.replace(settings.escape, "$1") : token),
\t \t \t \t // ignore type on non-moment tokens
\t \t \t \t type: ((type === "escape" || type === "general") ? null : type)
\t \t \t \t // calculate base value for all moment tokens
\t \t \t \t //baseValue: ((type === "escape" || type === "general") ? null : this.as(type))
\t \t \t };
\t \t }, this);
\t \t // unique moment token types in the template (in order of descending magnitude)
\t \t momentTypes = intersection(types, unique(compact(pluck(tokens, "type"))));
\t \t // exit early if there are no momentTypes
\t \t if (!momentTypes.length) {
\t \t \t return pluck(tokens, "token").join("");
\t \t }
\t \t // calculate values for each token type in the template
\t \t each(momentTypes, function (momentType, index) {
\t \t \t var value, wholeValue, decimalValue, isLeast, isMost;
\t \t \t // calculate integer and decimal value portions
\t \t \t value = remainder.as(momentType);
\t \t \t wholeValue = (value > 0 ? Math.floor(value) : Math.ceil(value));
\t \t \t decimalValue = value - wholeValue;
\t \t \t // is this the least-significant moment token found?
\t \t \t isLeast = ((index + 1) === momentTypes.length);
\t \t \t // is this the most-significant moment token found?
\t \t \t isMost = (!index);
\t \t \t // update tokens array
\t \t \t // using this algorithm to not assume anything about
\t \t \t // the order or frequency of any tokens
\t \t \t each(tokens, function (token) {
\t \t \t \t if (token.type === momentType) {
\t \t \t \t \t extend(token, {
\t \t \t \t \t \t value: value,
\t \t \t \t \t \t wholeValue: wholeValue,
\t \t \t \t \t \t decimalValue: decimalValue,
\t \t \t \t \t \t isLeast: isLeast,
\t \t \t \t \t \t isMost: isMost
\t \t \t \t \t });
\t \t \t \t \t if (isMost) {
\t \t \t \t \t \t // note the length of the most-significant moment token:
\t \t \t \t \t \t // if it is greater than one and forceLength is not set, default forceLength to `true`
\t \t \t \t \t \t if (settings.forceLength == null && token.length > 1) {
\t \t \t \t \t \t \t settings.forceLength = true;
\t \t \t \t \t \t }
\t \t \t \t \t \t // rationale is this:
\t \t \t \t \t \t // if the template is "h:mm:ss" and the moment value is 5 minutes, the user-friendly output is "5:00", not "05:00"
\t \t \t \t \t \t // shouldn't pad the `minutes` token even though it has length of two
\t \t \t \t \t \t // if the template is "hh:mm:ss", the user clearly wanted everything padded so we should output "05:00"
\t \t \t \t \t \t // if the user wanted the full padded output, they can set `{ trim: false }` to get "00:05:00"
\t \t \t \t \t }
\t \t \t \t }
\t \t \t });
\t \t \t // update remainder
\t \t \t remainder.subtract(wholeValue, momentType);
\t \t });
\t
\t \t // trim tokens array
\t \t if (settings.trim) {
\t \t \t tokens = (settings.trim === "left" ? rest : initial)(tokens, function (token) {
\t \t \t \t // return `true` if:
\t \t \t \t // the token is not the least moment token (don't trim the least moment token)
\t \t \t \t // the token is a moment token that does not have a value (don't trim moment tokens that have a whole value)
\t \t \t \t return !(token.isLeast || (token.type != null && token.wholeValue));
\t \t \t });
\t \t }
\t \t
\t \t
\t \t // build output
\t \t // the first moment token can have special handling
\t \t foundFirst = false;
\t \t // run the map in reverse order if trimming from the right
\t \t if (settings.trim === "right") {
\t \t \t tokens.reverse();
\t \t }
\t \t tokens = map(tokens, function (token) {
\t \t \t var val,
\t \t \t \t decVal;
\t \t \t if (!token.type) {
\t \t \t \t // if it is not a moment token, use the token as its own value
\t \t \t \t return token.token;
\t \t \t }
\t \t \t // apply negative precision formatting to the least-significant moment token
\t \t \t if (token.isLeast && (settings.precision < 0)) {
\t \t \t \t val = (Math.floor(token.wholeValue * Math.pow(10, settings.precision)) * Math.pow(10, -settings.precision)).toString();
\t \t \t } else {
\t \t \t \t val = token.wholeValue.toString();
\t \t \t }
\t \t \t
\t \t \t // remove negative sign from the beginning
\t \t \t val = val.replace(/^\-/, "");
\t \t \t // apply token length formatting
\t \t \t // special handling for the first moment token that is not the most significant in a trimmed template
\t \t \t if (token.length > 1 && (foundFirst || token.isMost || settings.forceLength)) {
\t \t \t \t val = padZero(val, token.length);
\t \t \t }
\t \t \t // add decimal value if precision > 0
\t \t \t if (token.isLeast && (settings.precision > 0)) {
\t \t \t \t decVal = token.decimalValue.toString().replace(/^\-/, "").split(/\.|e\-/);
\t \t \t \t switch (decVal.length) {
\t \t \t \t \t case 1:
\t \t \t \t \t \t val += "." + padZero(decVal[0], settings.precision, true).slice(0, settings.precision);
\t \t \t \t \t \t break;
\t \t \t \t \t \t
\t \t \t \t \t case 2:
\t \t \t \t \t \t val += "." + padZero(decVal[1], settings.precision, true).slice(0, settings.precision); \t \t
\t \t \t \t \t \t break;
\t \t \t \t \t \t
\t \t \t \t \t case 3:
\t \t \t \t \t \t val += "." + padZero(repeatZero((+decVal[2]) - 1) + (decVal[0] || "0") + decVal[1], settings.precision, true).slice(0, settings.precision); \t \t
\t \t \t \t \t \t break;
\t \t \t \t \t
\t \t \t \t \t default:
\t \t \t \t \t \t throw "Moment Duration Format: unable to parse token decimal value.";
\t \t \t \t }
\t \t \t }
\t \t \t
\t \t \t // add a negative sign if the value is negative and token is most significant
\t \t \t if (token.isMost && token.value < 0) {
\t \t \t \t val = "-" + val;
\t \t \t }
\t \t \t foundFirst = true;
\t \t \t return val;
\t \t });
\t \t // undo the reverse if trimming from the right
\t \t if (settings.trim === "right") {
\t \t \t tokens.reverse();
\t \t }
\t \t return tokens.join("");
\t };
\t moment.duration.fn.format.defaults = {
\t \t // token definitions
\t \t escape: /\[(.+?)\]/,
\t \t years: /[Yy]+/,
\t \t months: /M+/,
\t \t weeks: /[Ww]+/,
\t \t days: /[Dd]+/,
\t \t hours: /[Hh]+/,
\t \t minutes: /m+/,
\t \t seconds: /s+/,
\t \t milliseconds: /S+/,
\t \t general: /.+?/,
\t \t // token type names
\t \t // in order of descending magnitude
\t \t // can be a space-separated token name list or an array of token names
\t \t types: "escape years months weeks days hours minutes seconds milliseconds general",
\t \t // format options
\t \t // trim
\t \t // "left" - template tokens are trimmed from the left until the first moment token that has a value >= 1
\t \t // "right" - template tokens are trimmed from the right until the first moment token that has a value >= 1
\t \t // (the final moment token is not trimmed, regardless of value)
\t \t // `false` - template tokens are not trimmed
\t \t trim: "left",
\t \t // precision
\t \t // number of decimal digits to include after (to the right of) the decimal point (positive integer)
\t \t // or the number of digits to truncate to 0 before (to the left of) the decimal point (negative integer)
\t \t precision: 0,
\t \t // force first moment token with a value to render at full length even when template is trimmed and first moment token has length of 1
\t \t forceLength: null,
\t \t // template used to format duration
\t \t // may be a function or a string
\t \t // template functions are executed with the `this` binding of the settings object
\t \t // so that template strings may be dynamically generated based on the duration object
\t \t // (accessible via `this.duration`)
\t \t // or any of the other settings
\t \t template: function() {
\t \t \t var types = this.types,
\t \t \t \t dur = this.duration,
\t \t \t \t lastType = findLast(types, function (type) {
\t \t \t \t \t return dur._data[type];
\t \t \t \t });
\t \t \t // default template strings for each duration dimension type
\t \t \t switch (lastType) {
\t \t \t \t case "seconds":
\t \t \t \t \t return "h:mm:ss";
\t \t \t \t case "minutes":
\t \t \t \t \t return "d[d] h:mm";
\t \t \t \t case "hours":
\t \t \t \t \t return "d[d] h[h]";
\t \t \t \t case "days":
\t \t \t \t \t return "M[m] d[d]";
\t \t \t \t case "weeks":
\t \t \t \t \t return "y[y] w[w]";
\t \t \t \t case "months":
\t \t \t \t \t return "y[y] M[m]";
\t \t \t \t case "years":
\t \t \t \t \t return "y[y]";
\t \t \t \t default:
\t \t \t \t \t return "y[y] M[m] d[d] h:mm:ss";
\t \t \t }
\t \t }
\t };
})(this);
</script>
的[Java腳本轉換日期時間字符串大紀元]可能的複製(http://stackoverflow.com/questions/13707333/javascript-convert-date-time-string-to- epoch) –
我在鏈接中沒有看到任何有用的信息@DynoFu – programmerGuy
我以爲你使用的是香草javascript。解析時間戳字符串並使用Date.getTime()您有epoc,然後進行計算。 Icid有正確的答案。 http://momentjs.com/docs/#/durations/seconds/ –