formattingTokens,
} from '../format/format';
import checkOverflow from './check-overflow';
-import { HOUR } from '../units/constants';
+import { YEAR, HOUR } from '../units/constants';
import { hooks } from '../utils/hooks';
import getParsingFlags from './parsing-flags';
token,
skipped,
stringLength = string.length,
- totalParsedInputLength = 0;
+ totalParsedInputLength = 0,
+ era;
tokens =
expandFormat(config._f, config._locale).match(formattingTokens) || [];
config._meridiem
);
+ // handle era
+ era = getParsingFlags(config).era;
+ if (era !== null) {
+ config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
+ }
+
configFromArray(config);
checkOverflow(config);
}
overflow: -2,
charsLeftOver: 0,
nullInput: false,
+ invalidEra: null,
invalidMonth: null,
invalidFormat: false,
userInvalidated: false,
iso: false,
parsedDateParts: [],
+ era: null,
meridiem: null,
rfc2822: false,
weekdayMismatch: false,
!isNaN(m._d.getTime()) &&
flags.overflow < 0 &&
!flags.empty &&
+ !flags.invalidEra &&
!flags.invalidMonth &&
!flags.invalidWeekday &&
!flags.weekdayMismatch &&
import zeroFill from '../utils/zero-fill';
import isFunction from '../utils/is-function';
-var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
+var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
formatFunctions = {},
formatTokenFunctions = {};
import toInt from '../utils/to-int';
getSetGlobalLocale('en', {
+ eras: [
+ {
+ since: '0001-01-01',
+ until: +Infinity,
+ offset: 1,
+ name: 'Anno Domini',
+ narrow: 'AD',
+ abbr: 'AD',
+ },
+ {
+ since: '0000-12-31',
+ until: -Infinity,
+ offset: 1,
+ name: 'Before Christ',
+ narrow: 'BC',
+ abbr: 'BC',
+ },
+ ],
dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
ordinal: function (number) {
var b = number % 10,
proto.pastFuture = pastFuture;
proto.set = set;
+// Eras
+import {
+ localeEras,
+ localeErasParse,
+ localeErasConvertYear,
+ erasAbbrRegex,
+ erasNameRegex,
+ erasNarrowRegex,
+} from '../units/era';
+proto.eras = localeEras;
+proto.erasParse = localeErasParse;
+proto.erasConvertYear = localeErasConvertYear;
+proto.erasAbbrRegex = erasAbbrRegex;
+proto.erasNameRegex = erasNameRegex;
+proto.erasNarrowRegex = erasNarrowRegex;
+
// Month
import {
localeMonthsParse,
proto.valueOf = valueOf;
proto.creationData = creationData;
+// Era
+import { getEraName, getEraNarrow, getEraAbbr, getEraYear } from '../units/era';
+proto.eraName = getEraName;
+proto.eraNarrow = getEraNarrow;
+proto.eraAbbr = getEraAbbr;
+proto.eraYear = getEraYear;
+
// Year
import { getSetYear, getIsLeapYear } from '../units/year';
proto.year = getSetYear;
--- /dev/null
+import { addFormatToken } from '../format/format';
+import { addRegexToken, matchUnsigned, regexEscape } from '../parse/regex';
+import { addParseToken } from '../parse/token';
+import { YEAR } from './constants';
+import { hooks as moment } from '../utils/hooks';
+import { getLocale } from '../locale/locales';
+import getParsingFlags from '../create/parsing-flags';
+import hasOwnProp from '../utils/has-own-prop';
+
+addFormatToken('N', 0, 0, 'eraAbbr');
+addFormatToken('NN', 0, 0, 'eraAbbr');
+addFormatToken('NNN', 0, 0, 'eraAbbr');
+addFormatToken('NNNN', 0, 0, 'eraName');
+addFormatToken('NNNNN', 0, 0, 'eraNarrow');
+
+addFormatToken('y', ['y', 1], 'yo', 'eraYear');
+addFormatToken('y', ['yy', 2], 0, 'eraYear');
+addFormatToken('y', ['yyy', 3], 0, 'eraYear');
+addFormatToken('y', ['yyyy', 4], 0, 'eraYear');
+
+addRegexToken('N', matchEraAbbr);
+addRegexToken('NN', matchEraAbbr);
+addRegexToken('NNN', matchEraAbbr);
+addRegexToken('NNNN', matchEraName);
+addRegexToken('NNNNN', matchEraNarrow);
+
+addParseToken(['N', 'NN', 'NNN', 'NNNN', 'NNNNN'], function (
+ input,
+ array,
+ config,
+ token
+) {
+ var era = config._locale.erasParse(input, token, config._strict);
+ if (era) {
+ getParsingFlags(config).era = era;
+ } else {
+ getParsingFlags(config).invalidEra = input;
+ }
+});
+
+addRegexToken('y', matchUnsigned);
+addRegexToken('yy', matchUnsigned);
+addRegexToken('yyy', matchUnsigned);
+addRegexToken('yyyy', matchUnsigned);
+addRegexToken('yo', matchEraYearOrdinal);
+
+addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);
+addParseToken(['yo'], function (input, array, config, token) {
+ var match;
+ if (config._locale._eraYearOrdinalRegex) {
+ match = input.match(config._locale._eraYearOrdinalRegex);
+ }
+
+ if (config._locale.eraYearOrdinalParse) {
+ array[YEAR] = config._locale.eraYearOrdinalParse(input, match);
+ } else {
+ array[YEAR] = parseInt(input, 10);
+ }
+});
+
+export function localeEras(m, format) {
+ var i,
+ l,
+ date,
+ eras = this._eras || getLocale('en')._eras;
+ for (i = 0, l = eras.length; i < l; ++i) {
+ switch (typeof eras[i].since) {
+ case 'string':
+ // truncate time
+ date = moment(eras[i].since).startOf('day');
+ eras[i].since = date.valueOf();
+ break;
+ }
+
+ switch (typeof eras[i].until) {
+ case 'undefined':
+ eras[i].until = +Infinity;
+ break;
+ case 'string':
+ // truncate time
+ date = moment(eras[i].until).startOf('day').valueOf();
+ eras[i].until = date.valueOf();
+ break;
+ }
+ }
+ return eras;
+}
+
+export function localeErasParse(eraName, format, strict) {
+ var i,
+ l,
+ eras = this.eras(),
+ name,
+ abbr,
+ narrow;
+ eraName = eraName.toUpperCase();
+
+ for (i = 0, l = eras.length; i < l; ++i) {
+ name = eras[i].name.toUpperCase();
+ abbr = eras[i].abbr.toUpperCase();
+ narrow = eras[i].narrow.toUpperCase();
+
+ if (strict) {
+ switch (format) {
+ case 'N':
+ case 'NN':
+ case 'NNN':
+ if (abbr === eraName) {
+ return eras[i];
+ }
+ break;
+
+ case 'NNNN':
+ if (name === eraName) {
+ return eras[i];
+ }
+ break;
+
+ case 'NNNNN':
+ if (narrow === eraName) {
+ return eras[i];
+ }
+ break;
+ }
+ } else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
+ return eras[i];
+ }
+ }
+}
+
+export function localeErasConvertYear(era, year) {
+ var dir = era.since <= era.until ? +1 : -1;
+ if (year === undefined) {
+ return moment(era.since).year();
+ } else {
+ return moment(era.since).year() + (year - era.offset) * dir;
+ }
+}
+
+export function getEraName() {
+ var i,
+ l,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ // truncate time
+ val = this.startOf('day').valueOf();
+
+ if (eras[i].since <= val && val <= eras[i].until) {
+ return eras[i].name;
+ }
+ if (eras[i].until <= val && val <= eras[i].since) {
+ return eras[i].name;
+ }
+ }
+
+ return '';
+}
+
+export function getEraNarrow() {
+ var i,
+ l,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ // truncate time
+ val = this.startOf('day').valueOf();
+
+ if (eras[i].since <= val && val <= eras[i].until) {
+ return eras[i].narrow;
+ }
+ if (eras[i].until <= val && val <= eras[i].since) {
+ return eras[i].narrow;
+ }
+ }
+
+ return '';
+}
+
+export function getEraAbbr() {
+ var i,
+ l,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ // truncate time
+ val = this.startOf('day').valueOf();
+
+ if (eras[i].since <= val && val <= eras[i].until) {
+ return eras[i].abbr;
+ }
+ if (eras[i].until <= val && val <= eras[i].since) {
+ return eras[i].abbr;
+ }
+ }
+
+ return '';
+}
+
+export function getEraYear() {
+ var i,
+ l,
+ dir,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ dir = eras[i].since <= eras[i].until ? +1 : -1;
+
+ // truncate time
+ val = this.startOf('day').valueOf();
+
+ if (
+ (eras[i].since <= val && val <= eras[i].until) ||
+ (eras[i].until <= val && val <= eras[i].since)
+ ) {
+ return (
+ (this.year() - moment(eras[i].since).year()) * dir +
+ eras[i].offset
+ );
+ }
+ }
+
+ return this.year();
+}
+
+export function erasNameRegex(isStrict) {
+ if (!hasOwnProp(this, '_erasNameRegex')) {
+ computeErasParse.call(this);
+ }
+ return isStrict ? this._erasNameRegex : this._erasRegex;
+}
+
+export function erasAbbrRegex(isStrict) {
+ if (!hasOwnProp(this, '_erasAbbrRegex')) {
+ computeErasParse.call(this);
+ }
+ return isStrict ? this._erasAbbrRegex : this._erasRegex;
+}
+
+export function erasNarrowRegex(isStrict) {
+ if (!hasOwnProp(this, '_erasNarrowRegex')) {
+ computeErasParse.call(this);
+ }
+ return isStrict ? this._erasNarrowRegex : this._erasRegex;
+}
+
+function matchEraAbbr(isStrict, locale) {
+ return locale.erasAbbrRegex(isStrict);
+}
+
+function matchEraName(isStrict, locale) {
+ return locale.erasNameRegex(isStrict);
+}
+
+function matchEraNarrow(isStrict, locale) {
+ return locale.erasNarrowRegex(isStrict);
+}
+
+function matchEraYearOrdinal(isStrict, locale) {
+ return locale._eraYearOrdinalRegex || matchUnsigned;
+}
+
+function computeErasParse() {
+ var abbrPieces = [],
+ namePieces = [],
+ narrowPieces = [],
+ mixedPieces = [],
+ i,
+ l,
+ eras = this.eras();
+
+ for (i = 0, l = eras.length; i < l; ++i) {
+ namePieces.push(regexEscape(eras[i].name));
+ abbrPieces.push(regexEscape(eras[i].abbr));
+ narrowPieces.push(regexEscape(eras[i].narrow));
+
+ mixedPieces.push(regexEscape(eras[i].name));
+ mixedPieces.push(regexEscape(eras[i].abbr));
+ mixedPieces.push(regexEscape(eras[i].narrow));
+ }
+
+ this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');
+ this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');
+ this._erasNarrowRegex = new RegExp(
+ '^(' + narrowPieces.join('|') + ')',
+ 'i'
+ );
+}
import moment from '../moment';
export default moment.defineLocale('ja', {
+ eras: [
+ {
+ since: '1989-01-08',
+ offset: 1,
+ name: '平成',
+ narrow: '㍻',
+ abbr: 'H',
+ },
+ {
+ since: '1926-12-25',
+ until: '1989-01-07',
+ offset: 1,
+ name: '昭和',
+ narrow: '㍼',
+ abbr: 'S',
+ },
+ {
+ since: '1912-07-30',
+ until: '1926-12-24',
+ offset: 1,
+ name: '大正',
+ narrow: '㍽',
+ abbr: 'T',
+ },
+ {
+ since: '1873-01-01',
+ until: '1912-07-29',
+ offset: 6,
+ name: '明治',
+ narrow: '㍾',
+ abbr: 'M',
+ },
+ {
+ since: '0001-01-01',
+ until: '1873-12-31',
+ offset: 1,
+ name: '西暦',
+ narrow: 'AD',
+ abbr: 'AD',
+ },
+ {
+ since: '0000-12-31',
+ until: -Infinity,
+ offset: 1,
+ name: '紀元前',
+ narrow: 'BC',
+ abbr: 'BC',
+ },
+ ],
+ eraYearOrdinalRegex: /(元|\d+)年/,
+ eraYearOrdinalParse: function (input, match) {
+ return match[1] === '元' ? 1 : parseInt(match[1] || input, 10);
+ },
months: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split(
'_'
dayOfMonthOrdinalParse: /\d{1,2}日/,
ordinal: function (number, period) {
switch (period) {
+ case 'y':
+ return number === 1 ? '元年' : number + '年';
case 'd':
case 'D':
case 'DDD':
}
});
+test('parse era', function (assert) {
+ assert.equal(moment('2010 AD', 'y N', true).isValid(), true, '2010 AD');
+ assert.equal(moment('2010 AD', 'y N', true).year(), 2010, '2010 AD');
+
+ assert.equal(
+ moment('2010 Anno Domini', 'y N', true).isValid(),
+ false,
+ '2010 Anno Domini'
+ );
+ assert.equal(
+ moment('2010 Anno Domini', 'y N', false).isValid(),
+ true,
+ '2010 Anno Domini'
+ );
+ assert.equal(
+ moment('2010 Anno Domini', 'y NNNN', true).isValid(),
+ true,
+ '2010 Anno Domini'
+ );
+ assert.equal(
+ moment('2010 Anno Domini', 'y NNNN', true).year(),
+ 2010,
+ '2010 Anno Domini'
+ );
+ assert.equal(
+ moment('2010 Anno Domini', 'y N', false).year(),
+ 2010,
+ '2010 Anno Domini'
+ );
+
+ assert.equal(moment('469 BC', 'y N', true).isValid(), true, '469 BC');
+ assert.equal(moment('469 BC', 'y N', true).year(), -468, '469 BC');
+
+ assert.equal(
+ moment('469 Before Christ', 'y NNNN', true).isValid(),
+ true,
+ '469 Before Christ'
+ );
+ assert.equal(
+ moment('469 Before Christ', 'y NNNN', true).year(),
+ -468,
+ '469 Before Christ'
+ );
+});
+
+test('format era', function (assert) {
+ var a = [
+ ['+000001-01-01', 'N, NN, NNN', 'AD, AD, AD'],
+ ['+000001-01-01', 'NNNN', 'Anno Domini'],
+ ['+000001-01-01', 'NNNNN', 'AD'],
+ ['+000001-01-01', 'y', '1'],
+
+ ['+000000-12-31', 'N, NN, NNN', 'BC, BC, BC'],
+ ['+000000-12-31', 'NNNN', 'Before Christ'],
+ ['+000000-12-31', 'NNNNN', 'BC'],
+ ['+000000-12-31', 'y', '1'],
+
+ ['-000001-12-31', 'N, NN, NNN', 'BC, BC, BC'],
+ ['-000001-12-31', 'NNNN', 'Before Christ'],
+ ['-000001-12-31', 'NNNNN', 'BC'],
+ ['-000001-12-31', 'y', '2'],
+ ],
+ i,
+ l;
+
+ for (i = 0, l = a.length; i < l; ++i) {
+ assert.equal(
+ moment(a[i][0]).format(a[i][1]),
+ a[i][2],
+ a[i][0] + '; ' + a[i][1] + ' ---> ' + a[i][2]
+ );
+ }
+});
+
test('format ordinal', function (assert) {
assert.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st');
assert.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd');
}
});
+test('parse era', function (assert) {
+ // strict
+ assert.equal(
+ moment('平成30年', 'NNNNy年', true).isValid(),
+ true,
+ '平成30年'
+ );
+ assert.equal(moment('平成30年', 'NNNNy年', true).year(), 2018, '平成30年');
+ assert.equal(
+ moment('平成30年', 'NNNNyo', true).isValid(),
+ true,
+ '平成30年'
+ );
+ assert.equal(moment('平成30年', 'NNNNyo', true).year(), 2018, '平成30年');
+
+ assert.equal(moment('平成30年', 'Ny年', true).isValid(), false, '平成30年');
+ assert.equal(moment('平成30年', 'Ny年', false).isValid(), true, '平成30年');
+ assert.equal(moment('㍻30年', 'Ny年', true).isValid(), false, '㍻30年');
+ assert.equal(moment('㍻30年', 'Ny年', false).isValid(), true, '㍻30年');
+ assert.equal(moment('H30年', 'Ny年', false).isValid(), true, 'H30年');
+
+ // abbrv
+ assert.equal(moment('H30年', 'Ny年', true).isValid(), true, 'H30年');
+ assert.equal(moment('H30年', 'Ny年', true).year(), 2018, 'H30年');
+ assert.equal(moment('H30年', 'NNNNy年', true).isValid(), false, 'H30年');
+ assert.equal(moment('H30年', 'NNNNNy年', true).isValid(), false, 'H30年');
+
+ // narrow
+ assert.equal(moment('㍻30年', 'Ny年', true).isValid(), false, '㍻30年');
+ assert.equal(moment('㍻30年', 'NNNNy年', true).isValid(), false, '㍻30年');
+ assert.equal(moment('㍻30年', 'NNNNNy年', true).isValid(), true, '㍻30年');
+ assert.equal(moment('㍻30年', 'NNNNNy年', true).year(), 2018, '㍻30年');
+
+ // ordinal year
+ assert.equal(moment('平成30年', 'NNNNyo', true).year(), 2018, '平成30年');
+ assert.equal(moment('平成元年', 'NNNNyo', true).year(), 1989, '平成元年');
+
+ // old eras
+ assert.equal(moment('昭和64年', 'NNNNyo', true).year(), 1989, '昭和64年');
+ assert.equal(moment('昭和元年', 'NNNNyo', true).year(), 1926, '昭和元年');
+ assert.equal(moment('大正元年', 'NNNNyo', true).year(), 1912, '大正元年');
+ assert.equal(moment('明治6年', 'NNNNyo', true).year(), 1873, '明治6年');
+});
+
+test('format era', function (assert) {
+ var a = [
+ /* First day of Heisei Era */
+ ['+001989-01-08', 'N, NN, NNN', 'H, H, H'],
+ ['+001989-01-08', 'NNNN', '平成'],
+ ['+001989-01-08', 'NNNNN', '㍻'],
+ ['+001989-01-08', 'y yy yyy yyyy', '1 01 001 0001'],
+ ['+001989-01-08', 'yo', '元年'],
+
+ /* Last day of Showa Era */
+ ['+001989-01-07', 'N, NN, NNN', 'S, S, S'],
+ ['+001989-01-07', 'NNNN', '昭和'],
+ ['+001989-01-07', 'NNNNN', '㍼'],
+ ['+001989-01-07', 'y yy yyy yyyy', '64 64 064 0064'],
+ ['+001989-01-07', 'yo', '64年'],
+
+ /* Last day of Showa Era */
+ ['+001926-12-25', 'N, NN, NNN', 'S, S, S'],
+ ['+001926-12-25', 'NNNN', '昭和'],
+ ['+001926-12-25', 'NNNNN', '㍼'],
+ ['+001926-12-25', 'y yy yyy yyyy', '1 01 001 0001'],
+ ['+001926-12-25', 'yo', '元年'],
+
+ /* Last day of Taisho Era */
+ ['+001926-12-24', 'N, NN, NNN', 'T, T, T'],
+ ['+001926-12-24', 'NNNN', '大正'],
+ ['+001926-12-24', 'NNNNN', '㍽'],
+ ['+001926-12-24', 'y yy yyy yyyy', '15 15 015 0015'],
+ ['+001926-12-24', 'yo', '15年'],
+
+ /* First day of Taisho Era */
+ ['+001912-07-30', 'N, NN, NNN', 'T, T, T'],
+ ['+001912-07-30', 'NNNN', '大正'],
+ ['+001912-07-30', 'NNNNN', '㍽'],
+ ['+001912-07-30', 'y yy yyy yyyy', '1 01 001 0001'],
+ ['+001912-07-30', 'yo', '元年'],
+
+ /* Last day of Meiji Era */
+ ['+001912-07-29', 'N, NN, NNN', 'M, M, M'],
+ ['+001912-07-29', 'NNNN', '明治'],
+ ['+001912-07-29', 'NNNNN', '㍾'],
+ ['+001912-07-29', 'y yy yyy yyyy', '45 45 045 0045'],
+ ['+001912-07-29', 'yo', '45年'],
+
+ /* The day the Japanese government had began using the Gregorian calendar */
+ ['+001873-01-01', 'N, NN, NNN', 'M, M, M'],
+ ['+001873-01-01', 'NNNN', '明治'],
+ ['+001873-01-01', 'NNNNN', '㍾'],
+ ['+001873-01-01', 'y yy yyy yyyy', '6 06 006 0006'],
+ ['+001873-01-01', 'yo', '6年'],
+
+ /* Christinan Era */
+ ['+001872-12-31', 'N, NN, NNN', 'AD, AD, AD'],
+ ['+001872-12-31', 'NNNN', '西暦'],
+ ['+001872-12-31', 'NNNNN', 'AD'],
+ ['+001872-12-31', 'y yy yyy yyyy', '1872 1872 1872 1872'],
+ ['+001872-12-31', 'yo', '1872年'],
+
+ ['+000001-01-01', 'N, NN, NNN', 'AD, AD, AD'],
+ ['+000001-01-01', 'NNNN', '西暦'],
+ ['+000001-01-01', 'NNNNN', 'AD'],
+ ['+000001-01-01', 'y', '1'],
+
+ ['+000000-12-31', 'N, NN, NNN', 'BC, BC, BC'],
+ ['+000000-12-31', 'NNNN', '紀元前'],
+ ['+000000-12-31', 'NNNNN', 'BC'],
+ ['+000000-12-31', 'y', '1'],
+
+ ['-000001-12-31', 'N, NN, NNN', 'BC, BC, BC'],
+ ['-000001-12-31', 'NNNN', '紀元前'],
+ ['-000001-12-31', 'NNNNN', 'BC'],
+ ['-000001-12-31', 'y', '2'],
+ ],
+ i,
+ l;
+
+ for (i = 0, l = a.length; i < l; ++i) {
+ assert.equal(
+ moment(a[i][0]).format(a[i][1]),
+ a[i][2],
+ a[i][0] + '; ' + a[i][1] + ' ---> ' + a[i][2]
+ );
+ }
+});
+
test('format month', function (assert) {
var expected = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split(
'_'