質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

2回答

758閲覧

文字列定義された日付のフォーマットチェック機能のレシピ案

tama_yn0815

総合スコア143

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2020/04/16 11:37

編集2020/04/16 16:54

前提・実現したいこと

【環境】
language: JavaScript
ECMAScript: ECMA-262 5.1 edition
browser: Google Chrome (JavaScript エンジン V8)

【実現したいことの説明】
JavaScriptにて、文字列が指定されたフォーマットと一致するか?
チェックする機能(固定チェックではなく、汎用性のあるチェック機能)の実装について、
レシピ案を募集したいです。

今、スッと考え付くものでは、外部(呼出元)から正規表現を受け取る方式になるので、それは避けたい。

該当のソースコード

JavaScirpt

1"use strict"; 2 3(function (Str) { 4 // Stringオブジェクトの関数を追加 5 Str.prototype.format = format; 6 Str.prototype.formatCheck = formatCheck; 7 Str.prototype._formatCheckHelper = _formatCheckHelper; 8 9 function format () { 10 let _str = this; 11 // 'My name is {0} !'.format('Tama Shiro'); -> output 'My name is Tama Shiro !' 12 return (!arguments || arguments.length <= 0 ) ? _str : (function (str, args) { 13 for (var idx = 0, len = args.length; idx < len; idx++) { 14 str = str.replace(new RegExp('\{' + idx + '\}', 'g'), args[idx]); 15 } 16 return str; 17 })('' + _str, arguments); 18 } 19 function formatCheck (fmt) { 20 let _str = this; 21 return (_str.length < 1) ? void(0) : (check(_str, fmt)) ? true : false; 22 // let _helper = new _str._formatCheckHelper(_str, fmt); // <- 代案 23 // return (_str.length < 1) ? void(0) : (_helper.executeFormatCheck()) ? true : false; 24 25 function check (s, f) { // <- コレは冗長かも...直接、ヘルパーのチェックをcallする方が分かりやすい? 26 let _helper = new s._formatCheckHelper(s, f); 27 return _helper.executeFormatCheck();// こんな感じで呼び出したい 28 } 29 } 30 function _formatCheckHelper (str, fmt) { 31 if (!(this instanceof _formatCheckHelper)) { return void(0); } // メソッドとしてコールされた場合は何もせず返却 32 this.checkedString = str; 33 this.checkedFormat = fmt; 34 return this; // 受け取ったformatを正規表現化して返す..とか 35 } 36 // [以下、prototype代入を実行。。。。記述順は考慮外(関数評価と実行スコープの入れ子は無視ください。)] 37 // フォーマットと一致するかチェックする処理(親) 38 _formatCheckHelper.prototype.executeFormatCheck = function () { 39 let checkedResult = false; 40 // チェック処理 <- ここのアルゴリズムを検討したい 41 return checkedResult; 42 } 43 // 指定できるフォーマットのキーリスト 44 _formatCheckHelper.prototype._formatKeys = ['yyyy','yy','ee','e','ggg','gg','g','MMM','MM','M','dd','d','HH','H','hh','h','mm','m','ss','s','fff','f','TT','tt','DDD','DD']; 45 _formatCheckHelper.prototype._jp = { 46 // MMMで使用する日本の月名の配列 47 month: ['睦月', '如月', '弥生', '卯月', '皐月', '水無月', '文月', '葉月', '長月', '神無月', '霜月', '師走'], 48 // DDD、DDで使用する曜日に使用する配列 49 day: ['日', '月', '火', '水', '木', '金', '土'], 50 // TTで使用する配列 51 noonJp: ['午前', '午後'], 52 // ttで使用する配列 53 noonEn: ['AM', 'PM'] 54 }; 55 _formatCheckHelper.prototype._eras = { 56 // 西暦を最初に一致させる。。。javascriptの「for in」句の仕様(実行順)が変更されると不具合でます。。。その時は直す 57 AD: {name: 'AD', firstDate: 0, lastDate: 99999999, year: 0, yearDeff: 0, longName: '西暦', shortName: '西', alphaName: 'AD'}, 58 M: {name: 'M', firstDate: 18691023, lastDate: 19120729, year: 0, yearDeff: 1867, longName: '明治', shortName: '明', alphaName: 'M'}, 59 T: {name: 'T', firstDate: 19120730, lastDate: 19261224, year: 0, yearDeff: 1911, longName: '大正', shortName: '大', alphaName: 'T'}, 60 S: {name: 'S', firstDate: 19261225, lastDate: 19890107, year: 0, yearDeff: 1925, longName: '昭和', shortName: '昭', alphaName: 'S'}, 61 H: {name: 'H', firstDate: 19890108, lastDate: 20190430, year: 0, yearDeff: 1988, longName: '平成', shortName: '平', alphaName: 'H'}, 62 R: {name: 'R', firstDate: 20190501, lastDate: 99999999, year: 0, yearDeff: 2018, longName: '令和', shortName: '令', alphaName: 'R'} 63 }; 64 _formatCheckHelper.prototype.padSlice = function (val, num) { 65 val = (val == void(0)) ? 0 : val; 66 num = (num == void(0)) ? 2 : num; 67 return (new Array(num).join('0') + val).slice(num * -1); 68 }; 69})(String); 70 71// 実行 72(function () { 73 let dateString1 = '2020-01-11 12:46:16.234'; 74 let dateString2 = '2020月1月11日'; 75 window._TEST_RESULT = { 76 dateString1Check: dateString1.formatCheck('yyyy-MM-dd hh:mm:ss.fff'),// <- 期待は"True"(一致したよ) 77 dateString2Check: dateString2.formatCheck('yyyy/MM/dd')// <- 期待は"False"(一致しないよ) 78 }; 79 console.log(window._TEST_RESULT); 80})(); 81

試したこと

素の正規表現(個別に正規表現を定義して実行)は問題ない。。
困っているのは、フォーマットの指定を外部から**"文字列"**で受け取る形にすること

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

javascript

1const 2 FMT = Object.entries ({ 3 yyyy: '(\d{4})(?=\D|$)', 4 mm: '(0?[1-9]|1[0-2])(?=\D|$)', 5 dd: '(0?[1-9]|[12][0-9]|3[01])(?=\D|$)', 6 hh: '([01][0-9]|2[0-4])(?=\D|$)', 7 MM: '([0-5]?[0-9])(?=\D|$)', 8 ss: '([0-5]?[0-9])(?=\D|$)', 9 fff: '(\d{3})(?=\D|$)' 10 }), 11 12 check = (val,fmt)=>(new RegExp(FMT.reduce((str,arg)=> str.replace(...arg), `^${fmt}$`))).exec(val); 13 14 15console.log(check ("2020-12-31","yyyy-mm-dd")); 16console.log(check ("2020-12-31T12:34:56.999","yyyy-mm-ddThh:MM:ss.fff")); 17console.log(check ("2020-12-31T12:34:59","yyyy-mm-ddThh:MM:ss")); 18

1行?に収まりました。細かくは試していません。

投稿2020/04/17 02:46

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tama_yn0815

2020/04/17 04:40

回答をありがとうございます。 ちょっと試してみますね
guest

0

直接の回答では無いですが、他のプロムラム言語のライブラリを参考にするとかどうでしょうか。

例えば、C#(.net)とかだと、DateTimeクラスに文字列をDateTime型に変換できなかったらfalseを返す TryParseExact というメソッドがあります。(変換に成功したらtrueと変換したDateTimeの値を返します。)

ソースはC#ですが、こちらから確認できます。


ただ、汎用性を求めすぎると最終的に専用のチェックメソッドを必要に応じて実装したほうが使い勝手が良かったなんてことになりかねないのでやめておいたほうがいい気もします。

投稿2020/04/16 21:59

draq

総合スコア2573

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tama_yn0815

2020/04/17 04:34

回答をいただき、ありがとうございます! ライブラリを参考にですね。。。盲点でした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問