Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Date and Number formatting #362

Closed
wants to merge 2 commits into
from

Conversation

Projects
None yet
5 participants

As requested, branched with only the code, along with just the root locale data. Extra locale data has been removed.
(See also pr #348 which this is derived from.)

@rgrove rgrove commented on the diff Jan 14, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ return;
+ }
+ this._pattern = pattern;
+ this._segments = [];
+ this.Formats = formats;
+}
+
+// Data
+
+Format.prototype._pattern = null;
+Format.prototype._segments = null;
+
+//Exceptions
+
+Y.mix(Format, {
+ Exception: function(name, message) {
@rgrove

rgrove Jan 14, 2013

Contributor

Please don't define custom exception classes. This is widely considered bad practice in JS. In YUI, you should use Y.error().

@rgrove rgrove commented on the diff Jan 14, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+
+// Public methods
+
+Format.Segment.prototype.format = function(o) {
+ return this._s;
+};
+
+/**
+ * Parses the string at the given index, initializes the parse object
+ * (as appropriate), and returns the new index within the string for
+ * the next parsing step.
+ * <p>
+ * <strong>Note:</strong>
+ * This method must be implemented by sub-classes.
+ *
+ * @param o [object] The parse object to be initialized.
@rgrove

rgrove Jan 14, 2013

Contributor

Please use actual YUIDoc syntax.

@rgrove rgrove commented on the diff Jan 14, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ if (arguments.length == 0) return;
+ Format.TextSegment.superclass.constructor.call(this, format, s);
+};
+
+Y.extend(Format.TextSegment, Format.Segment);
+
+Format.TextSegment.prototype.toString = function() {
+ return "text: \""+this._s+'"';
+};
+
+Format.TextSegment.prototype.parse = function(o, s, index) {
+ return Format.Segment._parseLiteral(this._s, s, index);
+};
+
+if(String.prototype.trim == null) {
+ String.prototype.trim = function() {
@rgrove

rgrove Jan 14, 2013

Contributor

No.

Use Y.Lang.trim().

Edited: Removed editorial "WTF".

@jenny

jenny Jan 15, 2013

Owner

@rgrove Please stick to your very useful technical feedback and leave the editorials aside. It snarks the tone of our lovely open source community.

@rgrove rgrove commented on the diff Jan 14, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ case 2:
+ return zeroPad(month + 1, 2);
+ case 3:
+ return DateFormat.MonthSegment.MONTHS[DateFormat.MEDIUM][month];
+ case 5:
+ return DateFormat.MonthSegment.MONTHS[DateFormat.SHORT][month];
+ }
+ return DateFormat.MonthSegment.MONTHS[DateFormat.LONG][month];
+};
+
+//
+// Date week segment class
+//
+
+DateFormat.WeekSegment = function(format, s) {
+ if (arguments.length == 0) return;
@rgrove

rgrove Jan 14, 2013

Contributor

This repeated arguments.length pattern in constructor functions is ugly boilerplate that may affect performance (accessing the arguments object can prevent optimizations). It's not clear why it's necessary. If these constructors expect arguments, they should always expect arguments. If the arguments are optional, document them as optional and check for their presence without hitting arguments if possible.

@rgrove rgrove commented on the diff Jan 14, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ var pattern = "";
+ if(timePattern != "" && timeZonePattern != "") {
+ pattern = this._Formats.DateTimeTimezoneCombination;
+ } else if (timePattern != "") {
+ pattern = this._Formats.DateTimeCombination;
+ } else if(timeZonePattern != "") {
+ pattern = this._Formats.DateTimezoneCombination;
+ } else if(datePattern != ""){
+ //Just date
+ pattern = "{1}";
+ }
+
+ pattern = pattern.replace("{0}", timePattern).replace("{1}", datePattern).replace("{2}", timeZonePattern);
+
+ //Remove unnecessary whitespaces
+ pattern = pattern.replace(/\s\s+/g, " ").replace(/^\s+/, "").replace(/\s+$/, "");
@rgrove

rgrove Jan 14, 2013

Contributor

Use Y.Lang.trim().

@rgrove rgrove commented on the diff Jan 14, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+
+ if (s.length >= length) return s;
+
+ zeroChar = zeroChar || '0';
+
+ var a = [];
+ for (var i = s.length; i < length; i++) {
+ a.push(zeroChar);
+ }
+ a[rightSide ? "unshift" : "push"](s);
+
+ return a.join("");
+}
+
+if(String.prototype.trim == null) {
+ String.prototype.trim = function() {
@rgrove

rgrove Jan 14, 2013

Contributor

Another String.prototype modification? No.

@rgrove rgrove commented on the diff Jan 14, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ for (var i = 0; i < len; i++) {
+ if (!s.charAt(index++).match(/\d/)) {
+ index--;
+ break;
+ }
+ }
+ var tail = index;
+ if (head == tail) {
+ throw new Format.ParsingException("Number not present");
+ }
+ if (fixedlen && tail - head != fixedlen) {
+ throw new Format.ParsingException("Number too short");
+ }
+ var value = parseInt(s.substring(head, tail), radix || 10);
+ if (f) {
+ var target = o || window;
@rgrove

rgrove Jan 14, 2013

Contributor

Use Y.config.win in YUI, not window. Also, don't assume there's a window; this code may be running in Node.js.

@rgrove rgrove commented on the diff Jan 14, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ if (arguments.length == 0) return;
+ Format.TextSegment.superclass.constructor.call(this, format, s);
+};
+
+Y.extend(Format.TextSegment, Format.Segment);
+
+Format.TextSegment.prototype.toString = function() {
+ return "text: \""+this._s+'"';
+};
+
+Format.TextSegment.prototype.parse = function(o, s, index) {
+ return Format.Segment._parseLiteral(this._s, s, index);
+};
+
+if(String.prototype.trim == null) {
+ String.prototype.trim = function() {
@rgrove

rgrove Jan 14, 2013

Contributor

Stop modifying String.prototype. Srsly.

@rgrove rgrove commented on the diff Jan 14, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ ONE_UNIT_ABBREVIATED: 2,
+ ONE_UNIT_LONG: 4
+ }
+});
+
+//Public methods
+
+/**
+ * Formats a time value.
+ * One or two parameters are needed. If only one parameter is specified, this function formats the parameter relative to current time.
+ * If two parameters are specified, this function formats the first parameter relative to the second parameter.
+ * @param {Number} timeValue The time value (seconds since Epoch) to be formatted.
+ * @param {Number} relativeTo (Optional) The time value (seconds since Epoch) in relation to which timeValue should be formatted. It must be greater than or equal to timeValue, otherwise exception will be thrown.
+ * @return {String} The formatted string
+ */
+YRelativeTimeFormat.prototype.format = function(timeValue, relativeTo) {
@rgrove

rgrove Jan 14, 2013

Contributor

There's a huge amount of repetition in this function. Please come up with an implementation that doesn't rely on copy/paste.

@rgrove rgrove commented on the diff Jan 14, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ * @class YDurationFormat
+ * @constructor
+ * @param {Number} style selector for the desired duration format, from Y.Date.DURATION_FORMATS
+ */
+YDurationFormat = function(style) {
+ if(style && Y.Lang.isString(style)) {
+ style = Y.Date.DURATION_FORMATS[style];
+ }
+ this.style = style;
+ this.patterns = Y.Intl.get(MODULE_NAME);
+}
+
+//Exceptions
+
+Y.mix(YDurationFormat, {
+ IllegalArgumentsException: function(message) {
@rgrove

rgrove Jan 14, 2013

Contributor

Don't define custom exceptions.

@rgrove rgrove commented on the diff Jan 14, 2013

...date-advanced-format/datatype-date-advanced-format.js
+
+ if (s.length >= length) return s;
+
+ zeroChar = zeroChar || '0';
+
+ var a = [];
+ for (var i = s.length; i < length; i++) {
+ a.push(zeroChar);
+ }
+ a[rightSide ? "unshift" : "push"](s);
+
+ return a.join("");
+}
+
+if(String.prototype.trim == null) {
+ String.prototype.trim = function() {
@rgrove

rgrove Jan 14, 2013

Contributor

STOP IT.

For info: I've been working on parsing date/time strings into timestamps, along with relative changes - basically a full implementation of php's strtotime(), but with more (ie some) Internationalization support.

It's some way from being finished, but is https://github.com/mattparker/strtotime I intend it to go in the new gallery, eventually. The README will tell you what it does (and it does what it says): but I wouldn't suggest spending any time reading the code because there's a bunch of changes I want to make still (the code and I are on a break at the moment!).

More directly related to this: one thing that it occurred to me to do after the last lot of commits to strotime is to strip out timezone support (strtotime parses string timestamps, of which there are a lot), and which also appear here. And there's timezone string info (which could be significantly minified, incidentally) - so perhaps timezone data needs to be pulled out.

Other general comments on this PR: it's not at all clear what this does that Y.Date.format doesn't. I'm not actually very clear what this does do at all. It doesn't read like javascript.

Contributor

rgrove commented Jan 14, 2013

-1

This code makes no apparent effort to adhere to YUI best practices or coding standards. It hasn't even been linted. It is written in a verbose, repetitive, copy/paste-heavy, Java-like style that doesn't reflect modern JavaScript conventions. For example, in multiple places it modifies String.prototype to add a trim() method, which is not only a violation of fundamental good practice, it's also unnecessary because YUI has Y.Lang.trim().

Furthermore, the code is poorly commented, undocumented, and is presented here in a monolithic pull request with no description. It is virtually impossible to review, and my line comments above are merely a surface skim.

This should not go into YUI in this form or in anything like this form.

Owner

davglass commented Jan 15, 2013

After reading (or trying to read) this code, I'm a 👎 on this until it get's cleaned up.

There are several design flaws in this that make it unacceptable to merge in this format.

The String.prototype stuff is easy to replace and do properly, but there are very large parts of this code that just look "wrong" and look like they are a direct port from Java.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ return this._dateFormatInstance.format(date, relativeDate);
+}/**
+ * YRelativeTimeFormat class provides localized formatting of relative time values such as "3 minutes ago".
+ * Relative time formats supported are defined by how many units they may include.
+ * Relative time is only used for past events. The Relative time formats use appropriate singular/plural/paucal/etc. forms for all languages.
+ * In order to keep relative time formats independent of time zones, relative day names such as today, yesterday, or tomorrow are not used.
+ * @module format-relative
+ */
+
+var MODULE_NAME = "datatype-date-advanced-format";
+/**
+ * @class YRelativeTimeFormat
+ * @constructor
+ * @param {Number} style (Optional) Selector for the desired relative time format. If no argument is provided, default to ONE_UNIT_LONG. If argument is provided but is not a valid selector, an Error exception is thrown.
+ */
+YRelativeTimeFormat = function(style) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ return "BE"; //Only Buddhist Era supported for now
+};
+
+//
+// Start YUI code
+//
+
+/**
+ * @class YDateFormat
+ * @constructor
+ * @param {String} timeZone (Optional) TZ database ID for the time zone that should be used. If no argument is provided, "Etc/GMT" is used. If an argument is provided that is not a valid time zone identifier, an Error exception is thrown.
+ * @param {Number} dateFormat (Optional) Selector for the desired date format from Y.Date.DATE_FORMATS. If no argument is provided, NONE is assumed. If an argument is provided that's not a valid selector, an Error exception is thrown.
+ * @param {Number} timeFormat (Optional) Selector for the desired time format from Y.Date.TIME_FORMATS. If no argument is provided, NONE is assumed. If an argument is provided that's not a valid selector, an Error exception is thrown.
+ * @param {Number} timeZoneFormat (Optional) Selector for the desired time zone format from Y.Date.TIMEZONE_FORMATS. If no argument is provided, NONE is assumed. If an argument is provided that's not a valid selector, an Error exception is thrown.
+ */
+YDateFormat = function(timeZone, dateFormat, timeFormat, timeZoneFormat) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+// Date format class
+//
+
+/**
+ * The DateFormat class formats Date objects according to a specified
+ * pattern. The patterns are defined the same as the SimpleDateFormat
+ * class in the Java libraries.
+ * <p>
+ * <strong>Note:</strong>
+ * The date format differs from the Java patterns a few ways: the pattern
+ * "EEEEE" (5 'E's) denotes a <em>short</em> weekday and the pattern "MMMMM"
+ * (5 'M's) denotes a <em>short</em> month name. This matches the extended
+ * pattern found in the Common Locale Data Repository (CLDR) found at:
+ * http://www.unicode.org/cldr/.
+ */
+DateFormat = function(pattern, formats, timeZoneId) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+YUI.add('datatype-date-advanced-format', function (Y, NAME) {
+
+/*
+ * Copyright 2012 Yahoo! Inc. All Rights Reserved. Based on code owned by VMWare, Inc.
+ */
+
+//
+// Format class
+//
+
+/**
+ * Base class for all formats. To format an object, instantiate the
+ * format of your choice and call the <code>format</code> method which
+ * returns the formatted string.
+ */
+Format = function(pattern, formats) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+}
+/**
+ * YDurationFormat class formats time in a language independent manner.
+ * The duration formats use appropriate singular/plural/paucal/etc. forms for all languages.
+ * @module format-duration
+ * @requires format-numbers
+ */
+
+var MODULE_NAME = "datatype-date-advanced-format";
+/**
+ * YDurationFormat class formats time in a language independent manner.
+ * @class YDurationFormat
+ * @constructor
+ * @param {Number} style selector for the desired duration format, from Y.Date.DURATION_FORMATS
+ */
+YDurationFormat = function(style) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ return this._dateFormatInstance.format(date, relativeDate);
+}/**
+ * YRelativeTimeFormat class provides localized formatting of relative time values such as "3 minutes ago".
+ * Relative time formats supported are defined by how many units they may include.
+ * Relative time is only used for past events. The Relative time formats use appropriate singular/plural/paucal/etc. forms for all languages.
+ * In order to keep relative time formats independent of time zones, relative day names such as today, yesterday, or tomorrow are not used.
+ * @module format-relative
+ */
+
+var MODULE_NAME = "datatype-date-advanced-format";
+/**
+ * @class YRelativeTimeFormat
+ * @constructor
+ * @param {Number} style (Optional) Selector for the desired relative time format. If no argument is provided, default to ONE_UNIT_LONG. If argument is provided but is not a valid selector, an Error exception is thrown.
+ */
+YRelativeTimeFormat = function(style) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ ONE_UNIT_ABBREVIATED: 2,
+ ONE_UNIT_LONG: 4
+ }
+});
+
+//Public methods
+
+/**
+ * Formats a time value.
+ * One or two parameters are needed. If only one parameter is specified, this function formats the parameter relative to current time.
+ * If two parameters are specified, this function formats the first parameter relative to the second parameter.
+ * @param {Number} timeValue The time value (seconds since Epoch) to be formatted.
+ * @param {Number} relativeTo (Optional) The time value (seconds since Epoch) in relation to which timeValue should be formatted. It must be greater than or equal to timeValue, otherwise exception will be thrown.
+ * @return {String} The formatted string
+ */
+YRelativeTimeFormat.prototype.format = function(timeValue, relativeTo) {
@davglass

davglass Jan 15, 2013

Owner

This whole method has bad code smell, it's overly verbose and could easily be rewritten to not have all this "copied" logic in it.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ return "BE"; //Only Buddhist Era supported for now
+};
+
+//
+// Start YUI code
+//
+
+/**
+ * @class YDateFormat
+ * @constructor
+ * @param {String} timeZone (Optional) TZ database ID for the time zone that should be used. If no argument is provided, "Etc/GMT" is used. If an argument is provided that is not a valid time zone identifier, an Error exception is thrown.
+ * @param {Number} dateFormat (Optional) Selector for the desired date format from Y.Date.DATE_FORMATS. If no argument is provided, NONE is assumed. If an argument is provided that's not a valid selector, an Error exception is thrown.
+ * @param {Number} timeFormat (Optional) Selector for the desired time format from Y.Date.TIME_FORMATS. If no argument is provided, NONE is assumed. If an argument is provided that's not a valid selector, an Error exception is thrown.
+ * @param {Number} timeZoneFormat (Optional) Selector for the desired time zone format from Y.Date.TIMEZONE_FORMATS. If no argument is provided, NONE is assumed. If an argument is provided that's not a valid selector, an Error exception is thrown.
+ */
+YDateFormat = function(timeZone, dateFormat, timeFormat, timeZoneFormat) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+
+// Public methods
+
+DateFormat.TimezoneSegment.prototype.format = function(date) {
+ if (/Z/.test(this._s)) {
+ return this.getFormat().timeZone.getShortName();
+ }
+ return this._s.length < 4 ? this.getFormat().timeZone.getMediumName() : this.getFormat().timeZone.getLongName();
+};
+
+//
+// Non-Gregorian Calendars
+//
+
+//Buddhist Calendar. This is normally used only for Thai locales (th).
+BuddhistDateFormat = function(pattern, formats, timeZoneId, locale) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+// Date format class
+//
+
+/**
+ * The DateFormat class formats Date objects according to a specified
+ * pattern. The patterns are defined the same as the SimpleDateFormat
+ * class in the Java libraries.
+ * <p>
+ * <strong>Note:</strong>
+ * The date format differs from the Java patterns a few ways: the pattern
+ * "EEEEE" (5 'E's) denotes a <em>short</em> weekday and the pattern "MMMMM"
+ * (5 'M's) denotes a <em>short</em> month name. This matches the extended
+ * pattern found in the Common Locale Data Repository (CLDR) found at:
+ * http://www.unicode.org/cldr/.
+ */
+DateFormat = function(pattern, formats, timeZoneId) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+YUI.add('datatype-date-advanced-format', function (Y, NAME) {
+
+/*
+ * Copyright 2012 Yahoo! Inc. All Rights Reserved. Based on code owned by VMWare, Inc.
+ */
+
+//
+// Format class
+//
+
+/**
+ * Base class for all formats. To format an object, instantiate the
+ * format of your choice and call the <code>format</code> method which
+ * returns the formatted string.
+ */
+Format = function(pattern, formats) {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+Y.extend(Format.FormatException, Format.Exception);
+
+// Public methods
+
+Format.prototype.format = function(object) {
+ var s = [];
+
+ for (var i = 0; i < this._segments.length; i++) {
+ s.push(this._segments[i].format(object));
+ }
+ return s.join("");
+};
+
+// Protected static methods
+
+function zeroPad (s, length, zeroChar, rightSide) {
@davglass

davglass Jan 15, 2013

Owner

This method is defined in two separate places. that makes it a utility that needs to be shared and not privatized.

@davglass davglass commented on the diff Jan 15, 2013

...dvanced-format/datatype-date-advanced-format-debug.js
+ datePattern = "'<datePattern>'" + datePattern + "'</datePattern>'";
+ }
+
+ var pattern = "";
+ if(timePattern != "" && timeZonePattern != "") {
+ pattern = this._Formats.DateTimeTimezoneCombination;
+ } else if (timePattern != "") {
+ pattern = this._Formats.DateTimeCombination;
+ } else if(timeZonePattern != "") {
+ pattern = this._Formats.DateTimezoneCombination;
+ } else if(datePattern != ""){
+ //Just date
+ pattern = "{1}";
+ }
+
+ pattern = pattern.replace("{0}", timePattern).replace("{1}", datePattern).replace("{2}", timeZonePattern);
@davglass

davglass Jan 15, 2013

Owner

Y.Lang.sub would probably be better here.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+}
+/**
+ * YDateFormat provides absolute date and time formatting.
+ * Applications can choose date, time, and time zone components separately. For dates, relative descriptions (English "yesterday", German "vorgestern", Japanese "後天") are also supported.
+ * This module uses a few modified parts of zimbra AjxFormat to handle dates and time.
+ *
+ * Absolute formats use the default calendar specified in CLDR for each locale. Currently this means the Buddhist calendar for Thailand; the Gregorian calendar for all other countries.
+ * However, you can specify other calendars using language subtags; for example, for Thai the Gregorian calendar can be specified as th-TH-u-ca-gregory.
+ */
+
+var MODULE_NAME = "datatype-date-advanced-format";
+
+//
+// Resources
+//
+ShortNames = {
@davglass

davglass Jan 15, 2013

Owner

Global Variable.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ * (5 'M's) denotes a <em>short</em> month name. This matches the extended
+ * pattern found in the Common Locale Data Repository (CLDR) found at:
+ * http://www.unicode.org/cldr/.
+ */
+DateFormat = function(pattern, formats, timeZoneId) {
+ if (arguments.length == 0) {
+ return;
+ }
+ DateFormat.superclass.constructor.call(this, pattern, formats);
+ this.timeZone = new Y.Date.Timezone(timeZoneId);
+
+ if (pattern == null) {
+ return;
+ }
+ var head, tail, segment;
+ for (var i = 0; i < pattern.length; i++) {
@davglass

davglass Jan 15, 2013

Owner

Bad code smell here, 2 while loops, 2 for loops, continue's and break's just smells bad to me.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+//
+// Date month segment class
+//
+
+DateFormat.MonthSegment = function(format, s) {
+ if (arguments.length == 0) return;
+ DateFormat.MonthSegment.superclass.constructor.call(this, format, s);
+ this.initialize();
+};
+Y.extend(DateFormat.MonthSegment, DateFormat.DateSegment);
+
+DateFormat.MonthSegment.prototype.toString = function() {
+ return "dateMonth: \""+this._s+'"';
+};
+
+DateFormat.MonthSegment.prototype.initialize = function() {
@davglass

davglass Jan 15, 2013

Owner

var format = this.getFormat().Formats; Then reuse that. This is very hard to read

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ DateFormat.WeekSegment.superclass.constructor.call(this, format, s);
+};
+Y.extend(DateFormat.WeekSegment, DateFormat.DateSegment);
+
+// Public methods
+
+DateFormat.WeekSegment.prototype.format = function(date) {
+ var year = date.getYear();
+ var month = date.getMonth();
+ var day = date.getDate();
+
+ var ofYear = /w/.test(this._s);
+ var date2 = new Date(year, ofYear ? 0 : month, 1);
+
+ var week = 0;
+ while (true) {
@davglass

davglass Jan 15, 2013

Owner

while(true) Gives a bad smell here.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+//
+
+DateFormat.DaySegment = function(format, s) {
+ if (arguments.length == 0) return;
+ DateFormat.DaySegment.superclass.constructor.call(this, format, s);
+};
+Y.extend(DateFormat.DaySegment, DateFormat.DateSegment);
+
+// Public methods
+
+DateFormat.DaySegment.prototype.format = function(date) {
+ var month = date.getMonth();
+ var day = date.getDate();
+ if (/D/.test(this._s) && month > 0) {
+ var year = date.getYear();
+ do {
@davglass

davglass Jan 15, 2013

Owner

do ... while Bad code smell..

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+};
+Y.extend(DateFormat.WeekdaySegment, DateFormat.DateSegment);
+
+DateFormat.DaySegment.prototype.toString = function() {
+ return "dateDay: \""+this._s+'"';
+};
+
+DateFormat.WeekdaySegment.prototype.initialize = function() {
+ DateFormat.WeekdaySegment.WEEKDAYS = {};
+ // NOTE: The short names aren't available in Java so we have to define them.
+ DateFormat.WeekdaySegment.WEEKDAYS[DateFormat.SHORT] = [
+ ShortNames.weekdaySunShort,ShortNames.weekdayMonShort,ShortNames.weekdayTueShort,
+ ShortNames.weekdayWedShort,ShortNames.weekdayThuShort,ShortNames.weekdayFriShort,
+ ShortNames.weekdaySatShort
+ ];
+ DateFormat.WeekdaySegment.WEEKDAYS[DateFormat.MEDIUM] = [
@davglass

davglass Jan 15, 2013

Owner

var formats = this.getFormat().Formats; and reuse.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+
+// Public methods
+
+DateFormat.TimezoneSegment.prototype.format = function(date) {
+ if (/Z/.test(this._s)) {
+ return this.getFormat().timeZone.getShortName();
+ }
+ return this._s.length < 4 ? this.getFormat().timeZone.getMediumName() : this.getFormat().timeZone.getLongName();
+};
+
+//
+// Non-Gregorian Calendars
+//
+
+//Buddhist Calendar. This is normally used only for Thai locales (th).
+BuddhistDateFormat = function(pattern, formats, timeZoneId, locale) {
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+}
+/**
+ * YDurationFormat class formats time in a language independent manner.
+ * The duration formats use appropriate singular/plural/paucal/etc. forms for all languages.
+ * @module format-duration
+ * @requires format-numbers
+ */
+
+var MODULE_NAME = "datatype-date-advanced-format";
+/**
+ * YDurationFormat class formats time in a language independent manner.
+ * @class YDurationFormat
+ * @constructor
+ * @param {Number} style selector for the desired duration format, from Y.Date.DURATION_FORMATS
+ */
+YDurationFormat = function(style) {
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+ }
+
+ return {
+ hours: parseInt(matches[4] || -1),
+ minutes: parseInt(matches[5] || -1),
+ seconds: parseFloat(matches[6] || -1)
+ };
+}
+
+/**
+ * Get duration from time in seconds.
+ * The value should be integer value in seconds, and should not be negative.
+ * @param {Number} timeValueInSeconds Duration in seconds
+ * @return {Object} Duration as an object with the parameters hours, minutes and seconds.
+ */
+function getDuration_Seconds(timeValueInSeconds) {
@davglass

davglass Jan 15, 2013

Owner

We try not to have true private methods, add them to a Util object and add an underscore & api doc tags to show they are private.

@davglass davglass commented on the diff Jan 15, 2013

...date-advanced-format/datatype-date-advanced-format.js
+
+//Public methods
+
+/**
+ * Formats the given value into a duration format string. This function supports three kinds of usage, listed below:
+ * String format(int timeValueInSeconds):
+ * Formats the given value into a duration format string. The value should be integer value in seconds, and should not be negative.
+ * String format(string xmlDurationFormat):
+ * Formats the given XML duration format into a duration format string.
+ * The year/month/day fields are ignored in the final format string in this version. For future compatibility, please do not pass in the Year/Month/Day part in the parameter.
+ * For hour, minute, and second, absent parts are ignored in HMS_long format, but are treated as 0 in HMS_short format style.
+ * String format(int hour, int min, int second)
+ * Formats the given duration into a duration format string. Negative values are ignored in HMS_long format, but treated as 0 in HMS_short format.
+ * @return {String} The formatted string
+ */
+YDurationFormat.prototype.format = function() {
@davglass

davglass Jan 15, 2013

Owner

Use named arguments here, accessing arguments[x] is slow and reads very badly.

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
@@ -0,0 +1,3862 @@
+YUI.add('datatype-date-timezone', function (Y, NAME) {
+
+/*
+ * Copyright 2012 Yahoo! Inc. All Rights Reserved. Based on code owned by VMWare, Inc.
+ */
+TimezoneData = {};
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
@@ -0,0 +1,3862 @@
+YUI.add('datatype-date-timezone', function (Y, NAME) {
+
+/*
+ * Copyright 2012 Yahoo! Inc. All Rights Reserved. Based on code owned by VMWare, Inc.
+ */
+TimezoneData = {};
+
+TimezoneData.TRANSITION_YEAR = 2011;
+
+TimezoneData.TIMEZONE_RULES = [
@davglass

davglass Jan 15, 2013

Owner

There is a boat load of repetition in this meta-data, there needs to be a better way to ship this without it being this large.

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+ "Europe/Zagreb": "Europe/Belgrade",
+ "Europe/Bratislava": "Europe/Prague",
+ "America/Shiprock": "America/Denver",
+ "America/St_Barthelemy": "America/Guadeloupe",
+ "America/Marigot": "America/Guadeloupe"
+};
+/**
+ * Timezone performs operations on a given timezone string represented in Olson tz database
+ * This module uses parts of zimbra AjxTimezone to handle time-zones
+ * @module yTimezone
+ * @requires tzoneData, tzoneLinks, yDateFormatData
+ */
+
+var MODULE_NAME = "datatype-date-timezone";
+
+AjxTimezone = function() {
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+AjxTimezone.addRule = function(rule) {
+ var tzId = rule.tzId;
+
+ AjxTimezone._SHORT_NAMES[tzId] = AjxTimezone._generateShortName(rule.standard.offset);
+ AjxTimezone._CLIENT2RULE[tzId] = rule;
+
+ var array = rule.daylight ? AjxTimezone.DAYLIGHT_RULES : AjxTimezone.STANDARD_RULES;
+ array.push(rule);
+};
+
+AjxTimezone.getRule = function(tzId, tz) {
+ var rule = AjxTimezone._CLIENT2RULE[tzId];
+ if (!rule && tz) {
+ var names = [ "standard", "daylight" ];
+ var rules = tz.daylight ? AjxTimezone.DAYLIGHT_RULES : AjxTimezone.STANDARD_RULES;
+ for (var i = 0; i < rules.length; i++) {
@davglass

davglass Jan 15, 2013

Owner

3 nested for loops, bad code smell.

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+ return delta;
+};
+
+// Constants
+
+AjxTimezone._SHORT_NAMES = {};
+AjxTimezone._CLIENT2RULE = {};
+
+/**
+ * The data is specified using the server identifiers for historical
+ * reasons. Perhaps in the future we'll use the client (i.e. Java)
+ * identifiers on the server as well.
+ */
+AjxTimezone.STANDARD_RULES = [];
+AjxTimezone.DAYLIGHT_RULES = [];
+(function() {
@davglass

davglass Jan 15, 2013

Owner

Why the anon function?

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+ array.push(rule);
+ }
+})();
+
+AjxTimezone._generateShortName = function(offset, period) {
+ if (offset == 0) return "";
+ var sign = offset < 0 ? "-" : "+";
+ var stdOffset = Math.abs(offset);
+ var hours = Math.floor(stdOffset / 60);
+ var minutes = stdOffset % 60;
+ hours = hours < 10 ? '0' + hours : hours;
+ minutes = minutes < 10 ? '0' + minutes : minutes;
+ return [sign,hours,period?".":"",minutes].join("");
+};
+
+(function() {
@davglass

davglass Jan 15, 2013

Owner

Again, why?

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+ var hours = Math.floor(stdOffset / 60);
+ var minutes = stdOffset % 60;
+ hours = hours < 10 ? '0' + hours : hours;
+ minutes = minutes < 10 ? '0' + minutes : minutes;
+ return [sign,hours,period?".":"",minutes].join("");
+};
+
+(function() {
+ TimezoneData.TIMEZONE_RULES.sort(AjxTimezone._BY_OFFSET);
+ for (var j = 0; j < TimezoneData.TIMEZONE_RULES.length; j++) {
+ var rule = TimezoneData.TIMEZONE_RULES[j];
+ AjxTimezone.addRule(rule);
+ }
+})();
+
+Array.prototype.indexOf = function(obj) {
@davglass

davglass Jan 15, 2013

Owner

Never augment a native prototype, use Y.Array.indexOf

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+/**
+ * Get integer part of floating point argument
+ * @param floatNum A real number
+ * @return Integer part of floatNum
+ */
+function floatToInt(floatNum) {
+ return (floatNum < 0) ? Math.ceil(floatNum) : Math.floor(floatNum);
+}
+
+/**
+ * Timezone constructor. locale is optional, if not specified, defaults to root locale
+ * @class Timezone
+ * @constructor
+ * @param {String} tzId TimeZone ID as in Olson tz database
+ */
+Timezone = function(tzId) {
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

...atatype-date-timezone/datatype-date-timezone-debug.js
+ return (AjxTimezone._CLIENT2RULE[tzId] != null || TimezoneLinks[tzId] != null);
+}
+
+//
+// Start YUI Code
+//
+
+//Support methods first
+
+/**
+ * Pad number so that it is atleast num characters long
+ * @param {String} num String to be padded
+ * @param {Number} length (Optional) Minimum number of characters the string should have after padding. If omitted, defaults to 2
+ * @return {String} The padded string
+ */
+function zeroPad(num, length) {
@davglass

davglass Jan 15, 2013

Owner

Again, these should be in a Util namespace or something.

@davglass davglass commented on the diff Jan 15, 2013

build/datatype-date-timezone/datatype-date-timezone.js
@@ -0,0 +1,3862 @@
+YUI.add('datatype-date-timezone', function (Y, NAME) {
+
+/*
+ * Copyright 2012 Yahoo! Inc. All Rights Reserved. Based on code owned by VMWare, Inc.
+ */
+TimezoneData = {};
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

build/datatype-date-timezone/datatype-date-timezone.js
@@ -0,0 +1,3862 @@
+YUI.add('datatype-date-timezone', function (Y, NAME) {
+
+/*
+ * Copyright 2012 Yahoo! Inc. All Rights Reserved. Based on code owned by VMWare, Inc.
+ */
+TimezoneData = {};
+
+TimezoneData.TRANSITION_YEAR = 2011;
+
+TimezoneData.TIMEZONE_RULES = [
@davglass

davglass Jan 15, 2013

Owner

Why is this an array? Wouldn't this be easier if defined as an Object like this:

{
   "Asia/Riyadh88": {
        offset: 187
   }
}

@davglass davglass commented on the diff Jan 15, 2013

build/datatype-date-timezone/datatype-date-timezone.js
+ }
+},
+{
+ tzId: "America/Tortola",
+ standard: {
+ offset: -240
+ }
+},
+{
+ tzId: "America/St_Thomas",
+ standard: {
+ offset: -240
+ }
+}
+];
+TimezoneLinks = {
@davglass

davglass Jan 15, 2013

Owner

Global variable.

@davglass davglass commented on the diff Jan 15, 2013

build/datatype-date-timezone/datatype-date-timezone.js
+ "Europe/Zagreb": "Europe/Belgrade",
+ "Europe/Bratislava": "Europe/Prague",
+ "America/Shiprock": "America/Denver",
+ "America/St_Barthelemy": "America/Guadeloupe",
+ "America/Marigot": "America/Guadeloupe"
+};
+/**
+ * Timezone performs operations on a given timezone string represented in Olson tz database
+ * This module uses parts of zimbra AjxTimezone to handle time-zones
+ * @module yTimezone
+ * @requires tzoneData, tzoneLinks, yDateFormatData
+ */
+
+var MODULE_NAME = "datatype-date-timezone";
+
+AjxTimezone = function() {
@davglass

davglass Jan 15, 2013

Owner

Global variable.

Owner

davglass commented Jan 15, 2013

I pulled this in locally and I can't even get the tests to pass. It needs linting very badly and it needs it globals checked. I found way too may leaking vars.

Owner

davglass commented Jan 15, 2013

Just adding here for posterity: yogi [warn] lint found a total of 1063 errors.

Owner

davglass commented Jan 16, 2013

Forgot to mention that this all needs YUIDoc comments added to every function.

Owner

davglass commented Jan 16, 2013

Closed based on Open Hangout, recommending that this move into Gallery.

@davglass davglass closed this Jan 16, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment