日付表示を変更するには

解決


kuma  2007-06-28 23:01:40  No: 136854

VB.NET2003で開発です。

日付の表示を変更しようと思います。
2007/06/28  →  「28.JUN.07」に変換したいのですが、

VB6.0では、
Text1.Text = Format(Now, "DD.MMM.YY")  で「28.JUN.07」に
変換できていました。

ですが、.NET2003では
Text1.Text = dtNow.ToString("dd.MMM.yy") では「28.6.07」
Text1.Text = Format(dtNow, "dd.MMM.yy")  でも「28.6.07」に
なります。

他にもサイトや本を調べて試してみましたが、目的の形式に
表示できません。どうすれば変換できるのでしょうか。

開発環境は、WinXPで地域と言語のオプションは通常の「日本」です。
(中国、韓国でも利用予定です)

ご指導、よろしくお願い致します。


ためしてみて  2007-06-28 23:51:56  No: 136855

http://anetm.com/dev/tools/vbdotnet/112254.htm

とか?これで出来るかわかんないけど


魔界の仮面弁士  2007-06-29 00:27:21  No: 136856

> Text1.Text = dtNow.ToString("dd.MMM.yy") では「28.6.07」
> Text1.Text = Format(dtNow, "dd.MMM.yy")  でも「28.6.07」に
とは限りません。設定しだいでは、他の結果になることもあります。

> どうすれば変換できるのでしょうか。
System.Globalization 名前空間について調べてみましょう。
あとは、日付型の ToString メソッドの第 2 引数あたり。


kuma  2007-06-29 01:59:28  No: 136857

ためしてみてさん

ありがとうございます。
サイトの手順で作成してみましたが、結果は同じでした。
この環境の設定の問題でしょうか。

魔界の仮面弁士さん

ありがとうございます。設定ということですが、
全体を見てみましたが、該当しそうな設定が見つかりません。

System.Globalization 名前空間を調べてみました。
日付や言語等を定義しているということは分かりました。
そこからクラスの一覧も見つけてみましたが、利用法が理解できません。
また、
「日付型の ToString メソッドの第 2 引数」も、何を当てるのか見つかりません。

名前空間で、設定を変更する必要があるということでしょうか。


kuma  2007-06-29 02:09:11  No: 136858

「カルチャー情報に依存する」という情報を見つけました。
これが、設定と関係しているのでしょうか?

度々申し訳ありません。


魔界の仮面弁士  2007-06-29 02:31:07  No: 136859

> 全体を見てみましたが、該当しそうな設定が見つかりません。
Windows のコントロールパネルの地域設定です。

VB6 の場合も、
   s = Format(Now(), "yyyy/MM/dd hh:nn:ss")
の結果が、地域設定によって変化しましたよね。.NET でも同じです。

> 利用法が理解できません。
ヘルプには、具体的な使用例も書かれていると思いますけれども…。(^^;

で。今回の場合は、こんな感じですかね。

Dim cultureUS As New CultureInfo("en-us")
Dim result As String = Now.ToString("dd.MMM.yy", cultureUS)

ちなみに VB2005 だと、旧暦を扱う事もできるようになっています。


kuma  2007-06-29 03:02:56  No: 136860

魔界の仮面弁士 様

コンパネで設定を変えたら表示できました。気がつきませんでした。
設定は、この中のことだったのですね。
ですが、
全使用者の環境を変更することは出来ませんので、
この設定以外の方法が必要です。
VB6.0では、この設定指示は必要ありませんでした。

Dim cultureUS As New CultureInfo("en-us")
Dim result As String = Now.ToString("dd.MMM.yy", cultureUS)

上記を記述してみましたが、定義されていないとなります。
CultureInfoが無いようなので、Formの名称に変えてみましたら
今度は、引数が多いと、("en-us")を外すことになり、
結局例外エラーになってしまいました。

ヘルプの使用例を見ても分からないレベルだからでしょうか。。。
もう少しトライしてみます。


魔界の仮面弁士  2007-06-29 05:00:36  No: 136861

> 上記を記述してみましたが、定義されていないとなります。
ヘルプで、「CultureInfo クラス」について調べてみてください。
そしてそれは、なんという名前空間にありますか?

☆ヒント☆
>>>> System.Globalization 名前空間について調べてみましょう。
>>> System.Globalization 名前空間を調べてみました。

必要な名前空間さえ分かってしまえば、あとはそれを Imports するか、
もしくは、クラス名を(名前空間も含めた)フルネームで指定すれば、
正しく動作するかと思いますよ。

なお、CultureInfo を指定しなかった場合は、OS の地域設定が利用されます。

> 全使用者の環境を変更することは出来ませんので、

重要なのは、環境設定を変更することではありません。
環境設定に依存する可能性がある、という事を認識する事が重要なのです。

『実行環境の設定が反映されるべき』状況もあれば、
『実行環境に設定に依存しては困る』状況もあるからです。

特に今回のように、複数の国で使われる可能性がある場合において、
  『コンパネで設定したのに、その形式で表示/入力できない!』
  『コンパネの設定によって、動作が変わってしまう!』
のうち、どちらが正しい動作なのかは、アプリの目的/仕様によって異なります。

> VB6.0では、この設定指示は必要ありませんでした。
それは偶々です。"28.JUN.07" 形式の話に限った事ですよね。

むしろ、「A国の地域設定において、B国形式の表記を行わせたい」という状況下では、
VB6 の方が問題が大きくなってしまいます。CultureInfo に相当する指定ができませんから。

具体例を挙げてみましょうか。まずは、標準設定のままで
  '--- VB6
  S = Format(Now(), "yyyy/MM/dd")

  '--- VB.NET
  S = Now.ToString("yyyy/MM/dd")
を実行してみてください。おそらく、「2007/06/28」という文字列が得られるでしょう。

では次に、日付に関する地域設定を「和暦」にし、区切り文字を「/」から「-」に変更した状態で、
同じコードを実行してみてください。VB6 と VB.NET では、それぞれ異なる結果を返しますが、
いずれにしても、「2007/06/28」という文字列ではなく、別の結果を返してくるはずです。

日付以外の地域設定についても同様です。
たとえば、『Debug.Print CDbl("1,234") * 1000』という VB6 のコードを、
フランス設定やドイツ設定で動かすと、日本設定とは異なる結果となるでしょう。


kuma  2007-06-29 20:31:22  No: 136862

魔界の仮面弁士さん

ヘルプで「CultureInfo クラス」を調べてみました。
------------------------------------------------------------------
Imports System
Imports System.Globalization

public class printClass
  Public Shared Sub Main()  
   Dim ci As CultureInfo
   For Each ci In CultureInfo.GetCultures(CultureTypes.AllCultures)
     Console.WriteLine(ci)
   Next ci
  End Sub
End Class
-------------------------------------------------------------------
という使用例を見つけたので、
Imports System
Imports System.Globalization
だけ追加してみましたら、それだけでアドバイス頂いた
下記のコードで動きました。

Dim cultureUS As New CultureInfo("en-us")
Dim result As String = Now.ToString("dd.MMM.yy", cultureUS)

>必要な名前空間さえ分かってしまえば、あとはそれを Imports するか、
>もしくは、クラス名を(名前空間も含めた)フルネームで指定すれば、
>正しく動作するかと思いますよ。
ですが、名前空間がどれなのかが探せません。。。一体どれなのか。
Inherits System.Windows.Forms.Form  ←がフルネームでしょうか?

本を見ると、自分で作成するように感じますが作成した記憶はありません。

この方法は、
例えると「タイプライブラリへの参照設定の追加」に似てますか?
それを利用する為に、必要な環境を設定するような感じでしょうか。

今回の開発では、『実行環境の設定に依存しては困る』状況です。
なので、強制的に反映させたいです。

VB6のシステムで問題になっていなかったのは、偶然だったようです。^^;
一部を海外に依頼で、日本と環境設定がたまたま同じだったようです。
このこと、とっても勉強になりました。
5冊も購入したのにどこにも記載がなかったです。

区切り文字も、「/」と「-」両方入力可にする予定なので
ここもチェックしないといけませんでしたね。
地域設定がこんなに影響するとは思いませんでした。
開発PCとユーザーPCでの結果が変わるのも、そういうことが理由に
なったりしているのかもしれません。今後の検証ポイントにします。

Dim CheckData As DateTime  に  String  から変更したら
希望動作で変換できました。

これだけで問題解決にしてよろしいのでしょうか?
他にも必要ですか?


魔界の仮面弁士  2007-06-29 21:15:13  No: 136863

> ですが、名前空間がどれなのかが探せません。。。一体どれなのか。

ヘルプで「CultureInfo クラス」を調べたのですよね。
ならば、そのページ内に
    『名前空間: System.Globalization』
という記述も書かれているはずですよ。
http://msdn.microsoft.com/library/ja/cpref/html/frlrfSystemGlobalizationCultureInfoClassTopic.asp
http://msdn2.microsoft.com/ja-jp/library/system.globalization.cultureinfo%28VS.80%29.aspx

> Inherits System.Windows.Forms.Form  ←がフルネームでしょうか?
Inherits は継承のためのキーワードなので、ここでは関係無いですが、その後に続く
System.Windows.Forms.Form は、名前空間まで含めたフルネームでの指定です。
(名前空間指定を省略した場合は、単に Inherits Form と書ける)

Form クラスのフルネームは、System.Windows.Forms.Form です。
TextBox クラスのフルネームは、System.Windows.Forms.TextBox です。
CultureInfo クラスのフルネームは、System.Globalization.CultureInfo です。
String クラスのフルネームは、System.String です。

なので、
  Dim cultureUS As New CultureInfo("en-us")
をフルネームで書くならば、
  Dim cultureUS As New System.Globalization.CultureInfo("en-us")
となるわけです。

ただ、毎回フルネームを書くと面倒なので、省略できるようにインポート宣言を加えるわけです。

> 例えると「タイプライブラリへの参照設定の追加」に似てますか?
似ていますが、まったく別です。
必要な参照設定が不足していたら、プログラムはコンパイルできませんが、
名前空間のインポートはは必須事項ではありません。(省略表記できなくなるだけ)

参照設定は、「そのプロジェクトが、どのライブラリ(DLL等)を使用するか」です。
名前空間のインポートは、「フルネームを省略表記するための仕組み」です。

なお、インポート指定は、Imports ステートメントを使ってファイル単位で
指定することもできますが、プロジェクト単位での指定も可能です。
(既定では、System/System.Windows.Forms/Microsoft.VisualBasic等々がインポート済み)

> VB6のシステムで問題になっていなかったのは、偶然だったようです。^^;
ちなみに、VB6 で「2007/06/29」形式へのフォーマットを強制するなら、
  S = Format(Now(), "yyyy\/MM\/dd")
のように記述します。

> Dim CheckData As DateTime  に  String  から変更したら
> 希望動作で変換できました。
な、何の話ですか? (^^;)
突然、CheckData とか、DateTime → String  だとか言われても……。


kuma  2007-06-29 23:32:40  No: 136864

魔界の仮面弁士さん

>ヘルプで「CultureInfo クラス」を調べたのですよね。
>ならば、そのページ内に
>    『名前空間: System.Globalization』
>という記述も書かれているはずですよ
初めにありました。

<Serializable>
Public Class CultureInfo
   Implements ICloneable, IFormatProvider

上記が続きます。この後に使い方例もあります。
今は使い方の部分の意味が分かりました  ^^;  
魔界の仮面弁士さんの丁寧なご説明のおかげです。有難う御座います。

>Form クラスのフルネームは、System.Windows.Forms.Form です。
>TextBox クラスのフルネームは、System.Windows.Forms.TextBox です。
>CultureInfo クラスのフルネームは、System.Globalization.CultureInfo です。
>String クラスのフルネームは、System.String です。
もしかしたら、クラスを思い違いしていたようです。
そう考えるんですね。JavaとVBどれも中途半端なので勘違いもあるようです。

インポート宣言の利用意味も分かってきました。

>なお、インポート指定は、Imports ステートメントを使ってファイル単位で
>指定することもできますが、プロジェクト単位での指定も可能です。
ということは、どこかに記述すれば、全フォーム・プロシージャーに有効ということでしょうか?
探してみましたら、プロジェクトのプロパティの中に「インポート」と言う箇所があり、何点か入っています。そこに追加してみたら、宣言を外しても動作しました。これでもOKということでしょうか?

<ちなみに、VB6 で「2007/06/29」形式へのフォーマットを強制するなら、
<  S = Format(Now(), "yyyy\/MM\/dd")
<のように記述します。
S = UCase(Format(T1.Text, "DD.MMM.YY"))と書きました。それしか思いつかず。

>突然、CheckData とか、DateTime → String  だとか言われても……。
すみません。いきなりでした。
実際には、Nowではなく、入力値を変換するんです。なので
実は、Now以外の方法でも悩んでいたのが一度に解決できたのでついご報告をしてしまいました。失礼いたしました。


魔界の仮面弁士  2007-06-30 00:37:50  No: 136865

> <Serializable> _
> Public Class CultureInfo
>    Implements ICloneable, IFormatProvider
蛇足までに書いておくと、これらはそれぞれ
  Serializable 属性 → System.SerializableAttribute
  ICloneable インターフェイス → System.ICloneable
  IFormatProvider インターフェイス → System.IFormatProvider
というのが、名前空間まで含めた名前となります。

> そこに追加してみたら、宣言を外しても動作しました。
> これでもOKということでしょうか?
その通りです。(^^

> S = UCase(Format(T1.Text, "DD.MMM.YY"))と書きました。
VB6 でしょうか? であれば、書式文字列自体はそれで良いと思いますよ。

ただし Format の第 1 引数に、(Date 型ではなく)String 型の値を
渡している点については、再考の余地があるかも知れません。

というのも、このような String → Date への暗黙の型変換に対しても、
OS の『地域設定』が影響を与えることになるためです。くれぐれもご注意を。

> このこと、とっても勉強になりました。
> 5冊も購入したのにどこにも記載がなかったです。
地域設定/ロケールに関する記述は、ヘルプ上に含まれています。

VB6 ヘルプの[検索(S)]で、『国際対応のアプリケーション』を調べてみましょう。
.NET SDKの[キーワード]で、『国際対応のアプリケーション』を調べてみましょう。

> 入力値を変換するんです。
Date.Parse / Date.ParseExact メソッドを使って型変換すれば、カルチャを指定しての変換が可能です。
また、正しい日付形式かどうかの検証には、Date.TryParse / Date.TryParseExact メソッドが使えます。


kuma  2007-06-30 03:17:06  No: 136866

魔界の仮面弁士さん

正しい日付形式の検証・・・そんなことができるとは。
実は、入力可能文字を限定してある程度は抑制しておいて
「正しくない形式で入力したら変換値が不正になりますので訂正してください」
なんて荒業を仕様にして乗り切ろうかと考えてました。お恥ずかしいです。
早速変更します。

日付は、「'」が入ると変換できないようなので、『  "'" &  』としました。
VB6ではできたのに、.NETではエラーなんですね。
また、
VB6に関しては、やはり偶然が幸いしてバグ発生になっていないだけですね。
次回メンテリリースの際に検討してみます。
String型・Date型の区別が必要なことが分かってきました。
何でもStringにしているのは、間違いのようです。
ご教示ありがとうございます。

ヘルプも見てみました。本とは違うたくさんの説明がありました。
検索次第でしょうが、活用できれば正しい記述ができそうです。
まだ難しく見えますが。。。
エラーの原因になるようなことも発見できました。(書き直しました)


kuma  2007-07-02 19:43:23  No: 136867

魔界の仮面弁士さん

Date.TryParse も応用して、希望の状態でコーディングできました。
完成です。
細かくご指導頂き、本当に助かりました。
名前空間やメソッド等をもう一度調べてみます。とても参考になりました。

色々と有難う御座いました。

ためしてみてさん

有難う御座いました。利用させて頂きます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加