New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Duration missing features #463
Comments
+1 on this request |
@llacroix, would you be interested in writing a pull request for this? |
Yes probably, i'll try to find time for that. Adding it to momentjs will probably save myself and others time in the long run. Currently this forces me to create some kind of mess everywhere and it's not perfect. Fixing momentjs seems more appropriate. But we should probably discuss a bit more about what kind of format should be done. For example, should 0 values be displayed or not.
Months would be 30 days, a year 365. And what formats other than year, month, week, day, minute, second and millisecond should exist. |
+1 for this If round is not explicitely defined, I think the highest unity whose value is zero and all the units smaller than it should be omitted. // 1 hour 0 minutes 45 seconds Also, the "and" separator should be used for the last join, preceeded by whitespaces This is how I imagine that the function should behave by default |
Here's my suggestion for the signature and implementation. var duration = moment.duration({
hours : 1,
minutes : 0,
seconds : 20,
milliseconds : 0
});
duration.countdown(); // 1 hour 0 minutes 20 seconds
duration.countdown(1); // 1 hour
duration.countdown(2); // 1 hour and 0 minutes
duration.countdown(3); // 1 hour 0 minutes and 20 seconds As @sylvainpolletvillard suggested, we may want to add a parameter for trimming off zeroed values. Maybe something like this. duration.countdown(3); // 1 hour 0 minutes and 1 second
duration.countdown(3, true); // 1 hour We may also want to add a parameter for the suffix like duration.countdown(3); // 1 hour 0 minutes and 1 second ago
duration.countdown(3, null, true); // 1 hour ago We can build this somewhat easily for English, but concatenating all these strings correctly in all different languages will be very tricky. We will probably have to create callbacks for languages to concatenate strings themselves. These rules will probably be very complex (I'm looking at you, hungarian). I think the best way to pass these values would be something like the following. var keys = [ "h", "mm", "s"],
values = [ 1, 0, 20],
strings = ["1 hour", "0 minutes", "20 seconds"];
lang.countdown(keys, values, strings, addSuffix); Then the English translation would be something like this: lang.countdown = function (keys, values, strings, addSuffix) {
var i, output = "";
for (i = 0; i < strings.length; i++) {
if (i === strings.length - 1 && strings.length > 1) {
output += "and ";
}
output += strings[i] + " ";
}
if (addSuffix) {
output += "ago";
}
} All in all, this becomes an incredibly complex addition which would require 33 translation functions and a bunch more code in core. Also, I'm not sure how often it would be used, so it's adding all that bloat for everyone else. Perhaps this would be best moved to a plugin? |
Going back to the discussion on formatting the duration I think it would be great if something like this were possible -
Maybe providing a boolean parameter in the format method to determine whether 0 values were shown or not? |
CLDR has a list formatting scheme and data, which might be able to be used for many languages, probably many languages would still need custom callbacks though: http://cldr.unicode.org/development/development-process/design-proposals/list-formatting |
I'm pretty for the format function. Since implementing translation of multiple languages might be quite hard. Using formats should be quite easy to implement. Let say you want
No need for special callbacks but just special format strings. |
The proposed Meanwhile, is there a way to extend the Duration prototype? |
The duration prototype is exposed via |
I have been working on something similar last year on #143/#192. Tim suggested a plugin but I never took the time to do it. I was about to do reboot my work. I had to update to new concepts such as duration objects etc... I was this ticket and other ones. Now I'm struggling on wether it is still needed and if yes how should we implement that. I don't want to step on one's shoes so le met know if I can help. Who is working on that issue right now? My code was able to format to consecutive units and non consecutive units like that :
It didn't handle units that weren't in order like |
That looks awesome, exactly the kind of thing I was hoping for! |
This is definitely a needed feature for everyone. |
Need this! |
As a possible stopgap for some of you, I've created a simple plugin that allows you to use countdown.js directly from Moment: moment("1982-5-25").countdown().toString(); // => '30 years, 10 months, 14 days, 2 hours, 23 minutes, and 50 seconds' It passes through any Countdown options you pass it, like what units to use and with how much precision (you can look at the Countdown docs). Anyway, the plugin is here: https://github.com/icambron/moment-countdown |
@icambron thanks for your countribuiton! It's very helpful! |
I've just started using moment.js and pretty quickly came across this exact problem. This is the code I used to solve it: moment.duration.fn.format = function (input) {
var output = input;
var milliseconds = this.asMilliseconds();
var totalMilliseconds = 0;
var replaceRegexps = {
years: /Y(?!Y)/g,
months: /M(?!M)/g,
weeks: /W(?!W)/g,
days: /D(?!D)/g,
hours: /H(?!H)/g,
minutes: /m(?!m)/g,
seconds: /s(?!s)/g,
milliseconds: /S(?!S)/g
}
var matchRegexps = {
years: /Y/g,
months: /M/g,
weeks: /W/g,
days: /D/g,
hours: /H/g,
minutes: /m/g,
seconds: /s/g,
milliseconds: /S/g
}
for (var r in replaceRegexps) {
if (replaceRegexps[r].test(output)) {
var as = 'as'+r.charAt(0).toUpperCase() + r.slice(1);
var value = new String(Math.floor(moment.duration(milliseconds - totalMilliseconds)[as]()));
var replacements = output.match(matchRegexps[r]).length - value.length;
output = output.replace(replaceRegexps[r], value);
while (replacements > 0 && replaceRegexps[r].test(output)) {
output = output.replace(replaceRegexps[r], '0');
replacements--;
}
output = output.replace(matchRegexps[r], '');
var temp = {};
temp[r] = value;
totalMilliseconds += moment.duration(temp).asMilliseconds();
}
}
return output;
} Features of this code:
Possible problems:
|
+1 for this request Personally I think it makes more sense to implement I agree that Formatting duration is a must have. It should be easy to translate seconds in formated string. |
I try the stralytic code but: |
+1 for |
As a usecase, Durations used in timing exams (3 hours) can be formatted easily as hh:mm(:ss) or so, which would be so, so much more easier. Right now, it is quite tough to do the same in Moment until I dabble in vanilla js :) |
+1 duration format! here's the quick fix I used:
|
2019, still in need of this feature. |
A simple parameter in humanize, .e.g |
There is a great
Or if you want that between two specific dates you can use:
Taken from the Docs: |
Can this be reopened? This is very basic functionality. |
In my case I found a package which solved my problems: Maybe it is useful for someone else as well. :) |
July 2019 and this feature still not available. |
Haven't tried it yet, but I just noticed this! |
September 2019 still officially miss this feature d.format('H:mm:ss');
"1:01:01" Also wish that it could have this feature d.format('D-H:mm:ss'); // existence of D will mod hours to 24
"999-23:59:59" |
In case anyone was wondering why this was closed: #463 (comment) |
This is by no means ideal, but I ended up doing something like this as a workaround. I had a // What I did:
private getTimeString(duration: moment.Duration): string {
const time = moment()
.seconds(duration.seconds())
.minutes(duration.minutes());
return time.format('mm:ss');
}
// What I'd rather do (as many others have mentioned)...
private getTimeString(duration: moment.Duration): string {
return duration.format('mm:ss');
} |
A hacky solution of mine: import moment from 'moment';
const formatInt = (int: number): string => {
if (int < 10) {
return `0${int}`;
}
return `${int}`;
};
export const formatDuration = (time: string): string => {
const seconds = moment.duration(time).seconds();
const minutes = moment.duration(time).minutes();
const hours = moment.duration(time).hours();
if (hours > 0) {
return `${formatInt(hours)}:${formatInt(minutes)}:${formatInt(seconds)}`;
}
if (minutes > 0) {
return `${formatInt(minutes)}:${formatInt(seconds)}`;
}
return `00:${formatInt(seconds)}`;
}; |
2020 |
I use the following method, it may be useful to someone else :) function formatDuration(duration, format) {
const date = moment().startOf('day');
return date.add(duration).format(format);
} (I use it only to format durations between 00:00 and 23:59) |
Still need this |
These 'get' helps to format in way u want:
|
What I work with: const formatDuration = ms => {
const days = Math.floor(ms / 8.64e7);
const msOnLastDay = ms - days * 8.64e7;
return (days < 10 ? "0" + days : days) + ":" + moment.utc(msOnLastDay).format("HH:mm:ss.SSS");
}; formatDuration(5)
"00:00:00:00.005"
formatDuration(500)
"00:00:00:00.500"
formatDuration(50000)
"00:00:00:50.000"
formatDuration(5000000)
"00:01:23:20.000"
formatDuration(500000000)
"05:18:53:20.000"
// for reference
JSON.stringify(moment.duration(500000000)._data, null, 2)
"{
"milliseconds": 0,
"seconds": 20,
"minutes": 53,
"hours": 18,
"days": 5,
"months": 0,
"years": 0
}" |
This works perfectly fine :) |
The game is over :) |
Thanks, appreciate that!!!
…________________________________
De: Aleksey Makas <notifications@github.com>
Enviado: sexta-feira, 9 de outubro de 2020 11:03
Para: moment/moment <moment@noreply.github.com>
Cc: Douglas Aguiar <douglaszanquetta@hotmail.com>; Comment <comment@noreply.github.com>
Assunto: Re: [moment/moment] Duration missing features (#463)
The game is over :)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<#463 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AGD22DRNGNIQMOJFQY7VW3DSJ4J4VANCNFSM4ABRUZLA>.
|
2021, still in need of this feature. |
2022, still in need of this. |
My solution for a simple export function formatDuration(duration: moment.Duration) {
// convert 'P1D' to 'PT24H'
const isoString = moment.duration(duration.asMilliseconds()).toISOString();
// const [, , h = '', , m = '', , s = '', , ms = ''] =
const [, , h = '', , m = '', , s = ''] =
isoString.match(/T((\d+)H)?((\d+)M)?(([\d]+)(\.(\d+))?S)?/) ?? [];
// return `${h.padStart(2, '0')}:${m.padStart(2, '0')}:${s.padStart(2, '0')}.${ms.padStart(3, '0')}`;
return `${h.padStart(2, '0')}:${m.padStart(2, '0')}:${s.padStart(2, '0')}`;
} |
Summer 2022, we still in need of this feature... |
I'm surprised people have been asking for this feature for years and it's still not supported lol. |
As has been repeatedly discussed in this thread, internationalization concerns make it difficult-to-impossible to implement this feature with any sort of reasonable API. If you'd like to implement a library that implements this feature for a single locale, you're free to do so (there are numerous examples of this referenced above). However, working around the grammars of every locale that Moment supports (and gathering the relevant translation data) is a much more difficult proposition. If you've figured out how to build an i18n-friendly version of this API, you're also free to build that yourself. (Note that you'll need to fork Moment, as the project is in "maintenance mode", and the maintainers are not considering major new features.) Given Moment's deprecated status, you may want to consider making this a proper TC39 proposal as an extension of the Temporal API. I'm sure that many would consider this to be a valuable addition to the ECMAScript standard library. |
@schmod Partial support exists, but if you never start to implement it because it is too hard to do full support, then you will never complete it. I guess there are many people here, who know different languages, so adding a language would be just starting an enchancement issue and sumbitting some simple code. |
Summer 2023, still in need of this feature. |
I'm working on a project and momentjs is really useful for date manipulation so thanks for that.
To give you an example, we're making somekind of store for plane tickets. The
duration.humanize()
function is way to imprecise for us.For example when leaving at: 12:00 and landing at 13:30. It will round it to 2 hours. But we need some kind of granularity which is missing from momentjs.
humanize could default to 1 level of precision starting from the highest value.
The second problem is when there is the number 0. Momentjs translates it as "few seconds". I'm not so sure how it could be achieved but it would be cool to have some kind of formatting.
That way the highest value could be mapped in the format. So even if there is 1 year, the format tells us how to display it correctly. I'd be happy to push a commit for that because it's very useful and having to do it by hand when momentjs already handle localization feels bad.
The text was updated successfully, but these errors were encountered: