Skip to content
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

moment.fn.format escape multiple characters is partially broken by Localized date format #380

Closed
yelvert opened this issue Aug 1, 2012 · 8 comments
Labels

Comments

@yelvert
Copy link

yelvert commented Aug 1, 2012

It appears that the substitution for localized date format doesn't respect the multiple character escape.

moment().format('[Last] dddd') #> "MM/DD/YYYYast Monday"
moment().format('[LLL] LLL') #> "MMMM D YYYY h:mm A July 30 2012 8:47 AM"

rockymeza pushed a commit that referenced this issue Aug 3, 2012
rockymeza pushed a commit that referenced this issue Aug 3, 2012
@rockymeza
Copy link
Contributor

The problem is with how moment expands localFormattingTokens on line 381.

while (localFormattingTokens.test(format)) {
    format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
}

@timrwood, I'm not sure about how to fix this.

timrwood added a commit that referenced this issue Aug 3, 2012
@timrwood
Copy link
Member

timrwood commented Aug 3, 2012

So the way this works in 1.7.0 is that while there are still local formatting tokens in the string, it will replace them with the correct replacement. This is done to handle the recursive tokens like below.

LLL > MMMM D YYYY LT > MMMM D YYYY h:mm A

However, this also opens the possibility of an infinite loop if moment.longDateFormat.LLLL = 'LLLL'. The fix I made was to match anything inside braces in the localFormattingTokens regex, and only recurse twice through replacing local formatting tokens. This will cause things like the following not to work, but I don't think they are good practice anyway.

moment.longDateFormat.LT = "h:mm A";
moment.longDateFormat.L = "MM/DD/YYYY";
moment.longDateFormat.LL = "MMMM D YYYY";
moment.longDateFormat.LLL = "LL LT";
moment.longDateFormat.LLLL = "dddd, LLL";

If we think the above should be supported we'll have to think of another way to limit the while loop recursion. Maybe like this?

var lang = getLangDefinition(m), i = 5;

...

while (i-- && localFormattingTokens.test(format)) {
    format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
}

@yelvert
Copy link
Author

yelvert commented Aug 3, 2012

Why would the localDate formats not be implemented the same as other formats?

P.S. I'm on my phone and don't have the code in front of me, so this question may sound uninformed.

On Aug 3, 2012, at 11:28 AM, Tim Woodreply@reply.github.com wrote:

So the way this works in 1.7.0 is that while there are still local formatting tokens in the string, it will replace them with the correct replacement. This is done to handle the recursive tokens like below.

LLL > MMMM D YYYY LT > MMMM D YYYY h:mm A

However, this also opens the possibility of an infinite loop if moment.longDateFormat.LLLL = 'LLLL'. The fix I made was to match anything inside braces in the localFormattingTokens regex, and only recurse twice through replacing local formatting tokens. This will cause things like the following not to work, but I don't think they are good practice anyway.

moment.longDateFormat.LT = "h:mm A";
moment.longDateFormat.L = "MM/DD/YYYY";
moment.longDateFormat.LL = "MMMM D YYYY";
moment.longDateFormat.LLL = "LL LT";
moment.longDateFormat.LLLL = "dddd, LLL";

If we think the above should be supported we'll have to think of another way to limit the while loop recursion. Maybe like this?

var lang = getLangDefinition(m), i = 5;

...

while (i-- && localFormattingTokens.test(format)) {
   format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
}

Reply to this email directly or view it on GitHub:
#380 (comment)

@rockymeza
Copy link
Contributor

The localDate formats are actually more like macros than formats. They don't correspond to values, they correspond to other formats.

@yelvert
Copy link
Author

yelvert commented Aug 3, 2012

Ah ok, makes sense. In that case, would it be possible to apply the same escaping logic as the others?

@timrwood
Copy link
Member

timrwood commented Aug 3, 2012

Yeah, the commit I added fixes this, but it doesn't handle more than 2 levels of recursion as shown in my comment above.

@timrwood
Copy link
Member

Oops, forgot to tag this commit. 12aad5f

I added up to 5 levels of recursion and an early escape if it doesn't match L LL LLL LLLL LT. This should handle all the use cases outlined above.

@timrwood
Copy link
Member

timrwood commented Oct 1, 2012

This has been released with 1.7.1. #384

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants