Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 2k
World calendars#1220
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
Uh oh!
There was an error while loading. Please reload this page.
World calendars #1220
Changes from all commits
d2a5e4b61515754b9edec4d8f79a84a51c213cf6b1165125b86b31ea78b66461b563f54e9a632c1c24e8a4359816653da78e1747f00ae2dd3143099598410603ab34fdb3d18b05b2f9661ecd4268af287cb2c54bbc457a91444f5508f18cadcddceebbb76a48d8e9360e05f95509f2877bd501fFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /** | ||
| * Copyright 2012-2016, Plotly, Inc. | ||
| * All rights reserved. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
| 'use strict'; | ||
| module.exports = require('../src/components/calendars'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -69,14 +69,14 @@ function annAutorange(gd) { | ||
| } | ||
| if(xa && xa.autorange) { | ||
| Axes.expand(xa, [xa.l2c(xa.r2l(ann.x))], { | ||
| Axes.expand(xa, [xa.r2c(ann.x)], { | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 | ||
| ppadplus: rightSize, | ||
| ppadminus: leftSize | ||
| }); | ||
| } | ||
| if(ya && ya.autorange) { | ||
| Axes.expand(ya, [ya.l2c(ya.r2l(ann.y))], { | ||
| Axes.expand(ya, [ya.r2c(ann.y)], { | ||
| ppadplus: bottomSize, | ||
| ppadminus: topSize | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /** | ||
| * Copyright 2012-2016, Plotly, Inc. | ||
| * All rights reserved. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
| 'use strict'; | ||
| // a trimmed down version of: | ||
| // https://github.com/alexcjohnson/world-calendars/blob/master/dist/index.js | ||
| module.exports = require('world-calendars/dist/main'); | ||
| require('world-calendars/dist/plus'); | ||
| require('world-calendars/dist/calendars/chinese'); | ||
| require('world-calendars/dist/calendars/coptic'); | ||
| require('world-calendars/dist/calendars/discworld'); | ||
| require('world-calendars/dist/calendars/ethiopian'); | ||
| require('world-calendars/dist/calendars/hebrew'); | ||
| require('world-calendars/dist/calendars/islamic'); | ||
| require('world-calendars/dist/calendars/julian'); | ||
| require('world-calendars/dist/calendars/mayan'); | ||
| require('world-calendars/dist/calendars/nanakshahi'); | ||
| require('world-calendars/dist/calendars/nepali'); | ||
| require('world-calendars/dist/calendars/persian'); | ||
| require('world-calendars/dist/calendars/taiwan'); | ||
| require('world-calendars/dist/calendars/thai'); | ||
| require('world-calendars/dist/calendars/ummalqura'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,253 @@ | ||
| /** | ||
| * Copyright 2012-2016, Plotly, Inc. | ||
| * All rights reserved. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
| 'use strict'; | ||
| var calendars = require('./calendars'); | ||
| var Lib = require('../../lib'); | ||
| var constants = require('../../constants/numerical'); | ||
| var EPOCHJD = constants.EPOCHJD; | ||
| var ONEDAY = constants.ONEDAY; | ||
| var attributes = { | ||
| valType: 'enumerated', | ||
| values: Object.keys(calendars.calendars), | ||
| role: 'info', | ||
| dflt: 'gregorian' | ||
| }; | ||
| var handleDefaults = function(contIn, contOut, attr, dflt) { | ||
| var attrs = {}; | ||
| attrs[attr] = attributes; | ||
| return Lib.coerce(contIn, contOut, attrs, attr, dflt); | ||
| }; | ||
| var handleTraceDefaults = function(traceIn, traceOut, coords, layout) { | ||
| for(var i = 0; i < coords.length; i++) { | ||
| handleDefaults(traceIn, traceOut, coords[i] + 'calendar', layout.calendar); | ||
| } | ||
| }; | ||
| // each calendar needs its own default canonical tick. I would love to use | ||
| // 2000-01-01 (or even 0000-01-01) for them all but they don't necessarily | ||
| // all support either of those dates. Instead I'll use the most significant | ||
| // number they *do* support, biased toward the present day. | ||
| var CANONICAL_TICK = { | ||
| chinese: '2000-01-01', | ||
| coptic: '2000-01-01', | ||
| discworld: '2000-01-01', | ||
| ethiopian: '2000-01-01', | ||
| hebrew: '5000-01-01', | ||
| islamic: '1000-01-01', | ||
| julian: '2000-01-01', | ||
| mayan: '5000-01-01', | ||
| nanakshahi: '1000-01-01', | ||
| nepali: '2000-01-01', | ||
| persian: '1000-01-01', | ||
| jalali: '1000-01-01', | ||
| taiwan: '1000-01-01', | ||
| thai: '2000-01-01', | ||
| ummalqura: '1400-01-01' | ||
| }; | ||
| // Start on a Sunday - for week ticks | ||
| // Discworld and Mayan calendars don't have 7-day weeks but we're going to give them | ||
| // 7-day week ticks so start on our Sundays. | ||
| // If anyone really cares we can customize the auto tick spacings for these calendars. | ||
| var CANONICAL_SUNDAY = { | ||
| chinese: '2000-01-02', | ||
| coptic: '2000-01-03', | ||
| discworld: '2000-01-03', | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bug fix or typo? CollaboratorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see the comment change above - I decided it would be better to keep our Sundays unless and until we support the native weeks in these calendars. | ||
| ethiopian: '2000-01-05', | ||
| hebrew: '5000-01-01', | ||
| islamic: '1000-01-02', | ||
| julian: '2000-01-03', | ||
| mayan: '5000-01-01', | ||
| nanakshahi: '1000-01-05', | ||
| nepali: '2000-01-05', | ||
| persian: '1000-01-01', | ||
| jalali: '1000-01-01', | ||
| taiwan: '1000-01-04', | ||
| thai: '2000-01-04', | ||
| ummalqura: '1400-01-06' | ||
| }; | ||
| var DFLTRANGE = { | ||
| chinese: ['2000-01-01', '2001-01-01'], | ||
| coptic: ['1700-01-01', '1701-01-01'], | ||
| discworld: ['1800-01-01', '1801-01-01'], | ||
| ethiopian: ['2000-01-01', '2001-01-01'], | ||
| hebrew: ['5700-01-01', '5701-01-01'], | ||
| islamic: ['1400-01-01', '1401-01-01'], | ||
| julian: ['2000-01-01', '2001-01-01'], | ||
| mayan: ['5200-01-01', '5201-01-01'], | ||
| nanakshahi: ['0500-01-01', '0501-01-01'], | ||
| nepali: ['2000-01-01', '2001-01-01'], | ||
| persian: ['1400-01-01', '1401-01-01'], | ||
| jalali: ['1400-01-01', '1401-01-01'], | ||
| taiwan: ['0100-01-01', '0101-01-01'], | ||
| thai: ['2500-01-01', '2501-01-01'], | ||
| ummalqura: ['1400-01-01', '1401-01-01'] | ||
| }; | ||
| /* | ||
| * convert d3 templates to world-calendars templates, so our users only need | ||
| * to know d3's specifiers. Map space padding to no padding, and unknown fields | ||
| * to an ugly placeholder | ||
| */ | ||
| var UNKNOWN = '##'; | ||
| var d3ToWorldCalendars = { | ||
| 'd': {'0': 'dd', '-': 'd'}, // 2-digit or unpadded day of month | ||
| 'a': {'0': 'D', '-': 'D'}, // short weekday name | ||
| 'A': {'0': 'DD', '-': 'DD'}, // full weekday name | ||
| 'j': {'0': 'oo', '-': 'o'}, // 3-digit or unpadded day of the year | ||
| 'W': {'0': 'ww', '-': 'w'}, // 2-digit or unpadded week of the year (Monday first) | ||
| 'm': {'0': 'mm', '-': 'm'}, // 2-digit or unpadded month number | ||
| 'b': {'0': 'M', '-': 'M'}, // short month name | ||
| 'B': {'0': 'MM', '-': 'MM'}, // full month name | ||
| 'y': {'0': 'yy', '-': 'yy'}, // 2-digit year (map unpadded to zero-padded) | ||
| 'Y': {'0': 'yyyy', '-': 'yyyy'}, // 4-digit year (map unpadded to zero-padded) | ||
| 'U': UNKNOWN, // Sunday-first week of the year | ||
| 'w': UNKNOWN, // day of the week [0(sunday),6] | ||
| // combined format, we replace the date part with the world-calendar version | ||
| // and the %X stays there for d3 to handle with time parts | ||
| '%c': {'0': 'D M m %X yyyy', '-': 'D M m %X yyyy'}, | ||
| '%x': {'0': 'mm/dd/yyyy', '-': 'mm/dd/yyyy'} | ||
| }; | ||
| function worldCalFmt(fmt, x, calendar) { | ||
| var dateJD = Math.floor(x + 0.05 / ONEDAY) + EPOCHJD, | ||
| cDate = getCal(calendar).fromJD(dateJD), | ||
| i = 0, | ||
| modifier, directive, directiveLen, directiveObj, replacementPart; | ||
| while((i = fmt.indexOf('%', i)) !== -1) { | ||
| modifier = fmt.charAt(i + 1); | ||
| if(modifier === '0' || modifier === '-' || modifier === '_') { | ||
| directiveLen = 3; | ||
| directive = fmt.charAt(i + 1); | ||
| if(modifier === '_') modifier = '-'; | ||
| } | ||
| else { | ||
| directive = modifier; | ||
| modifier = '0'; | ||
| directiveLen = 2; | ||
| } | ||
| directiveObj = d3ToWorldCalendars[directive]; | ||
| if(!directiveObj) { | ||
| i += directiveLen; | ||
| } | ||
| else { | ||
| // code is recognized as a date part but world-calendars doesn't support it | ||
| if(directiveObj === UNKNOWN) replacementPart = UNKNOWN; | ||
| // format the cDate according to the translated directive | ||
| else replacementPart = cDate.formatDate(directiveObj[modifier]); | ||
| fmt = fmt.substr(0, i) + replacementPart + fmt.substr(i + directiveLen); | ||
| i += replacementPart.length; | ||
| } | ||
| } | ||
| return fmt; | ||
| } | ||
| // cache world calendars, so we don't have to reinstantiate | ||
| // during each date-time conversion | ||
| var allCals = {}; | ||
| function getCal(calendar) { | ||
| var calendarObj = allCals[calendar]; | ||
| if(calendarObj) return calendarObj; | ||
| calendarObj = allCals[calendar] = calendars.instance(calendar); | ||
| return calendarObj; | ||
| } | ||
| function makeAttrs(description) { | ||
| return Lib.extendFlat({}, attributes, { description: description }); | ||
| } | ||
| function makeTraceAttrsDescription(coord) { | ||
| return 'Sets the calendar system to use with `' + coord + '` date data.'; | ||
| } | ||
| var xAttrs = { | ||
| xcalendar: makeAttrs(makeTraceAttrsDescription('x')) | ||
| }; | ||
| var xyAttrs = Lib.extendFlat({}, xAttrs, { | ||
| ycalendar: makeAttrs(makeTraceAttrsDescription('y')) | ||
| }); | ||
| var xyzAttrs = Lib.extendFlat({}, xyAttrs, { | ||
| zcalendar: makeAttrs(makeTraceAttrsDescription('z')) | ||
| }); | ||
| var axisAttrs = makeAttrs([ | ||
| 'Sets the calendar system to use for `range` and `tick0`', | ||
| 'if this is a date axis. This does not set the calendar for', | ||
| 'interpreting data on this axis, that\'s specified in the trace', | ||
| 'or via the global `layout.calendar`' | ||
| ].join(' ')); | ||
| module.exports = { | ||
| moduleType: 'component', | ||
| name: 'calendars', | ||
| schema: { | ||
| traces: { | ||
| scatter: xyAttrs, | ||
| bar: xyAttrs, | ||
| heatmap: xyAttrs, | ||
| contour: xyAttrs, | ||
| histogram: xyAttrs, | ||
| histogram2d: xyAttrs, | ||
| histogram2dcontour: xyAttrs, | ||
| scatter3d: xyzAttrs, | ||
| surface: xyzAttrs, | ||
| mesh3d: xyzAttrs, | ||
| scattergl: xyAttrs, | ||
| ohlc: xAttrs, | ||
| candlestick: xAttrs | ||
| }, | ||
| layout: { | ||
| calendar: makeAttrs([ | ||
| 'Sets the default calendar system to use for interpreting and', | ||
| 'displaying dates throughout the plot.' | ||
| ].join(' ')), | ||
| 'xaxis.calendar': axisAttrs, | ||
| 'yaxis.calendar': axisAttrs, | ||
| 'scene.xaxis.calendar': axisAttrs, | ||
| 'scene.yaxis.calendar': axisAttrs, | ||
| 'scene.zaxis.calendar': axisAttrs | ||
| }, | ||
| transforms: { | ||
| filter: { | ||
| calendar: makeAttrs([ | ||
| 'Sets the calendar system to use for `value`, if it is a date.', | ||
| 'Note that this is not necessarily the same calendar as is used', | ||
| 'for the target data; that is set by its own calendar attribute,', | ||
| 'ie `trace.x` uses `trace.xcalendar` etc.' | ||
| ].join(' ')) | ||
| } | ||
| } | ||
| }, | ||
| layoutAttributes: attributes, | ||
| handleDefaults: handleDefaults, | ||
| handleTraceDefaults: handleTraceDefaults, | ||
| CANONICAL_SUNDAY: CANONICAL_SUNDAY, | ||
| CANONICAL_TICK: CANONICAL_TICK, | ||
| DFLTRANGE: DFLTRANGE, | ||
| getCal: getCal, | ||
| worldCalFmt: worldCalFmt | ||
| }; | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍻