著者は、 Diversity in Tech Fund を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

ソフトウェアは、仕事をより簡単に行えるように設計されており、多くの人にとって、日付と時刻の操作が含まれます。 日付と時刻の値は、最新のソフトウェアのいたるところに表示されます。 たとえば、車がいつサービスを必要とするかを追跡して所有者に知らせたり、データベース内の変更を追跡して監査ログを作成したり、ある時間を別の時間と比較してプロセスにかかった時間を判断したりします。 したがって、現在の時刻を取得し、時刻の値を操作して情報を抽出し、わかりやすい形式でユーザーに表示することは、アプリケーションの重要な特性です。

このチュートリアルでは、コンピューターの現在の現地時間を取得するGoプログラムを作成し、それを人々が読みやすい形式で画面に印刷します。 次に、文字列を解釈して日付と時刻の情報を抽出します。 また、2つのタイムゾーン間の日付と時刻の値を変換し、時刻の値を加算または減算して2つの時間の間隔を決定します。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • Goバージョン1.16以降がインストールされています。これは、シリーズGoのローカルプログラミング環境をインストールおよびセットアップする方法に従って実行できます。

現在の時刻を取得する

このセクションでは、Goのtimeパッケージを使用して現在の時刻を取得します。 Goの標準ライブラリのtimeパッケージは、日付と時刻に関連するさまざまな関数を提供し、time.Timeタイプを使用して特定の時点を表すために使用できます。 時刻と日付に加えて、表された日付と時刻が含まれるタイムゾーンに関する情報も保持できます。

timeパッケージを探索するプログラムの作成を開始するには、ファイル用のディレクトリを作成する必要があります。 このディレクトリは、コンピュータのどこにでも作成できますが、多くの開発者はプロジェクト用のディレクトリを持っている傾向があります。 このチュートリアルでは、projectsという名前のディレクトリを使用します。

projectsディレクトリを作成し、次の場所に移動します。

  1. mkdir projects
  2. cd projects

projectsディレクトリから、mkdirを実行してdatetimeディレクトリを作成し、cdを使用してそのディレクトリに移動します。

  1. mkdir datetime
  2. cd datetime

プロジェクトディレクトリを作成したら、nanoまたはお好みのエディタを使用してmain.goファイルを開きます。

  1. nano main.go

main.goファイルに、現在の時刻を取得して出力するmain関数を追加します。

projects / datetime / main.go
package main

import (
	"fmt"
	"time"
)

func main() {
	currentTime := time.Now()
	fmt.Println("The time is", currentTime)
}

このプログラムでは、timeパッケージのtime.Now関数を使用して、現在の現地時間をtime.Time値として取得し、currentTimeに格納します。 ] 変数。 変数に格納されると、fmt.Println関数は、time.Timeのデフォルトの文字列出力形式を使用してcurrentTimeを画面に出力します。

go runmain.goファイルを使用してプログラムを実行します。

  1. go run main.go

現在の日付と時刻を示す出力は、次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626

出力には現在の日付と時刻が表示されますが、これは例とは異なります。 さらに、time.Now()はローカルタイムゾーンの時刻を返すため、表示されるタイムゾーン(この出力では-0500 CDT)は異なる可能性があります。

また、出力にm=の値が表示される場合があります。 この値は単調時計であり、時間の差を測定するときにGoによって内部的に使用されます。 単調クロックは、プログラムの実行中にコンピュータのシステムクロックの日付と時刻が変更される可能性を補正するように設計されています。 単調クロックを使用することにより、5分後のtime.Now値と比較したtime.Now値は、システムクロックがその5分間の間に、コンピューターが1時間前後に変更されます。 このチュートリアルのコードや例について完全に理解する必要はありませんが、単調時計とGoの使用方法について詳しく知りたい場合は、timeパッケージのドキュメントには、追加の詳細が記載されています。

これで、現在の時刻が表示されますが、ユーザーにとっては役に立たない場合があります。 探している形式ではないか、表示したい日付または時刻の一部が含まれている可能性があります。

幸い、time.Timeタイプには、必要な日付または時刻の特定の部分を取得するためのさまざまなメソッドが含まれています。 たとえば、currentTime変数の年の部分だけを知りたい場合は、Yearメソッドを使用するか、Hourメソッドを使用して現在の時間を取得できます。

main.goファイルを再度開き、time.Timeメソッドのいくつかを出力に追加して、それらが何を生成するかを確認します。

projects / datetime / main.go
...

func main() {
	currentTime := time.Now()
	fmt.Println("The time is", currentTime)
	
	fmt.Println("The year is", currentTime.Year())
	fmt.Println("The month is", currentTime.Month())
	fmt.Println("The day is", currentTime.Day())
	fmt.Println("The hour is", currentTime.Hour())
	fmt.Println("The minute is", currentTime.Hour())
	fmt.Println("The second is", currentTime.Second())
}

次に、go runを使用してプログラムを再実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626 The year is 2021 The month is August The day is 15 The hour is 14 The minute is 14 The second is 45

前の出力と同様に、現在の日付と時刻は例とは異なりますが、形式は類似している必要があります。 今回の出力では、以前と同じように完全な日付と時刻が印刷されますが、年、月、日、時、分、秒のリストもあります。 月が数字として印刷されるのではなく(完全な日付のように)、英語の文字列Augustとして表示されることに注意してください。 これは、Monthメソッドが月を数値ではなく、time.Monthタイプとして返すためです。このタイプは、[として出力されるときに完全な英語名を出力するように設計されています。 X189X]。

ここで、プログラムのmain.goファイルを再度更新し、さまざまな関数出力をfmt.Printfへの単一の関数呼び出しに置き換えて、現在の日付と時刻をより近い形式で印刷できるようにします。ユーザーに表示したい場合があります:

projects / datetime / main.go
...

func main() {
	currentTime := time.Now()
	fmt.Println("The time is", currentTime)
	
	fmt.Printf("%d-%d-%d %d:%d:%d\n",
		currentTime.Year(),
		currentTime.Month(),
		currentTime.Day(),
		currentTime.Hour(),
		currentTime.Hour(),
		currentTime.Second())
}

更新をmain.goファイルに保存したら、前と同じようにgo runコマンドを使用して実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626 2021-8-15 14:14:45

今回の出力は希望するものにかなり近いかもしれませんが、出力に関して微調整できることがいくつかあります。 fmt.Printf形式は%dを使用してtime.Monthタイプに、stringではなく数字を使用する必要があるため、月は再び数値形式で表示されます。 ]ですが、1桁でしか表示されません。 2桁を表示する場合は、fmt.Printf形式を変更してそのようにすることができますが、上記の出力に示すように、24時間制ではなく12時間制も表示する場合はどうでしょうか。 fmt.Printfメソッドを使用すると、それを計算するために独自の計算を行う必要があります。 fmt.Printfを使用して日付と時刻を印刷することは可能ですが、ご覧のとおり、最終的には面倒になる可能性があります。 このようにすると、表示するパーツごとに多数の行が作成されるか、表示する内容を決定するために独自の計算を行う必要があります。

このセクションでは、time.Nowを使用して現在の時刻を取得する新しいプログラムを作成しました。 現在時刻を取得したら、time.TimeタイプのYearHourなどのさまざまな機能を使用して、現在時刻に関する情報を出力します。 ただし、カスタム形式で表示するのは大変な作業になり始めました。 このタイプの一般的な作業を簡単にするために、Goを含む多くのプログラミング言語は、fmt.Printfを使用して文字列をフォーマットする方法と同様に、日付と時刻をフォーマットする特別な方法を提供します。

特定の日付の印刷とフォーマット

YearHour、およびtime.Timeタイプが提供するその他のデータ関連のメソッドに加えて、Formatと呼ばれるメソッドも提供します。 Formatメソッドを使用すると、fmt.Printfまたはfmt.Sprintfの形式を提供するのと同様に、Format日付と時刻をどのように印刷するかを方法で説明します。 このセクションでは、前のセクションで追加した時間出力を複製しますが、Formatメソッドを使用するとはるかに簡潔になります。

ただし、Formatメソッドを使用する前に、プログラムを実行するたびに変更されない場合、Formatが日付と時刻の出力にどのように影響するかを簡単に確認できます。 これまでは、time.Nowを使用して現在の時刻を取得していたため、実行するたびに異なる番号が表示されていました。 Go timeパッケージは、time.Timeが表す特定の日時を指定できるtime.Date関数というもう1つの便利な関数を提供します。

プログラムでtime.Nowの代わりにtime.Dateの使用を開始するには、main.goファイルを再度開き、time.Nowtime.Dateに置き換えるように更新します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
}

time.Date関数のパラメーターには、time.Timeを使用する日時の年、月、日、時、分、秒が含まれます。 最後の2つのパラメーターの最初はナノ秒を占め、最後のパラメーターは時間を作成するためのタイムゾーンです。 タイムゾーン自体の使用については、このチュートリアルの後半で説明します。

更新を保存した後、go runを使用してプログラムを実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT

プログラムの実行時に現在の日付と時刻ではなく特定のローカルの日付と時刻を使用しているため、表示される出力は上記の出力に非常に近くなるはずです。 (ただし、コンピューターが設定されているタイムゾーンによっては、タイムゾーンの表示が異なる場合があります。)出力形式は、デフォルトのtime.Time形式を使用しているため、以前と同じように表示されます。 作業する標準の日時ができたので、これを使用して、Formatメソッドを使用して表示するときの時刻のフォーマット方法の調整を開始できます。

Formatメソッドを使用した日付文字列のカスタマイズ

他の多くのプログラミング言語には、表示する日付と時刻をフォーマットする同様の方法が含まれていますが、Goがこれらのフォーマットのレイアウトを構築する方法は、他の言語で使用した場合とは少し異なる場合があります。 他の言語では、日付の書式設定は、PrintfがGoで機能するのと同様のスタイルを使用し、%文字の後に、挿入する日付または時刻の一部を表す文字が続きます。 たとえば、4桁の年は%Yで表されます。 ただし、Goでは、日付または時刻のこれらの部分は、特定の日付を表す文字で表されます。 Go日付形式で4桁の年を含めるには、実際には文字列自体に2006を含めます。 このタイプのレイアウトの利点は、コードに表示される内容が実際に出力に表示される内容を表すことです。 出力の表現を見ることができると、フォーマットが探しているものと一致することを再確認しやすくなり、他の開発者がプログラムを実行せずにプログラムの出力を理解しやすくなります。最初にプログラムします。

Goが文字列形式の日付と時刻のレイアウトに使用する特定の日付は01/02 03:04:05PM '06 -0700です。 日付と時刻の各コンポーネントを見ると、パーツごとに1つずつ増加していることがわかります。 月は最初に01で、次に月の日が02で、次に時が03で、分が04で、2番目が05で、06(または2006)で年、そして最後に07でタイムゾーン。 この順序を覚えておくと、将来の日付と時刻の形式を簡単に作成できるようになります。 フォーマットに使用できるオプションの例は、Goのタイムパッケージのドキュメントにもあります。

次に、この新しいFormatメソッドを使用して、前のセクションで印刷した日付形式を複製してクリーンアップします。 表示するには数行と関数呼び出しが必要でした。Formatメソッドを使用すると、複製がはるかに簡単でクリーンになります。

main.goファイルを開き、新しいfmt.Println呼び出しを追加して、Formatメソッドを使用してフォーマットされた日付でtheTimeを渡します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)

	fmt.Println(theTime.Format("2006-1-2 15:4:5"))
}

フォーマットに使用されているレイアウトを見ると、上から同じ時刻を使用して、日付と時刻のフォーマット方法を指定していることがわかります(2006年1月2日)。 注意すべき点の1つは、前の例のように03ではなく15を使用していることです。 これは、12時間形式ではなく24時間形式で時間を表示することを希望していることを示しています。

この新しい形式からの出力を表示するには、プログラムを保存し、go runを使用して実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-8-15 14:30:45

ここに表示される出力は、前のセクションの終わりからの出力と似ていますが、実行するのがはるかに簡単でした。 含める必要があるのは、1行のコードとレイアウト文字列だけでした。 Format関数が残りの作業を行います。

表示している日付または時刻によっては、数値を直接印刷するときに使用したような可変長形式を使用すると、自分自身、ユーザー、または値を読み取ろうとする他のコードが読みにくくなる可能性があります。 月の形式に1を使用すると、3月は3と表示され、10月は2文字を使用して10と表示されます。 次に、main.goを開き、別のより構造化されたレイアウトでプログラムに行を追加します。 このレイアウトでは、コンポーネントに0プレフィックスを含め、12時間形式を使用するように時間を更新します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)

	fmt.Println(theTime.Format("2006-1-2 15:4:5"))
	fmt.Println(theTime.Format("2006-01-02 03:04:05 pm"))
}

コードを保存した後、go runを使用してプログラムを再実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-8-15 14:30:45 2021-08-15 02:30:45 pm

レイアウト文字列の数値に0プレフィックスを追加すると、新しい出力の月の8がレイアウトに一致する08になることがわかります。 現在は12時間形式になっている時間にも、独自の0プレフィックスが付いています。 ただし、最終的には、出力に表示される内容はコードに表示される形式を反映しているため、必要に応じて形式を微調整する方が簡単です。

多くの場合、フォーマットされた日付は他のプログラムによって解釈されることを意図しており、使用するたびにそれらのフォーマットを再作成するのは負担になる可能性があります。 場合によっては、事前定義された形式を使用できます。

事前定義された形式の使用

ログメッセージのタイムスタンプなど、一般的に使用される日付形式は多数あり、使用するたびにそれらを再作成すると、面倒になる可能性があります。 これらの場合のいくつかでは、timeパッケージには、使用できる事前定義された形式が含まれています。

利用可能で頻繁に使用される形式の1つは、 RFC3339で定義されている形式です。 RFC は、インターネット上の標準がどのように機能するかを定義するために使用されるドキュメントであり、他のRFCは相互に構築できます。 たとえば、HTTPがどのように機能するかを定義するRFC( RFC 2616 )や、HTTPをさらに定義するためにその上に構築されるRFCがあります。 したがって、RFC 3339の場合、RFCは、インターネット上のタイムスタンプに使用する標準形式を定義します。 このフォーマットはインターネット上でよく知られており、十分にサポートされているため、他の場所で見られる可能性が高くなります。

timeパッケージで事前定義された各時間形式は、それらが表す形式にちなんで名付けられたconst stringで表されます。 RFC 3339形式には、time.RFC3339と呼ばれる形式とtime.RFC3339Nanoと呼ばれる形式の2つの形式があります。 フォーマット間の違いは、time.RFC3339Nanoバージョンのフォーマットにナノ秒が含まれていることです。

次に、main.goファイルを再度開き、出力にtime.RFC3339Nano形式を使用するようにプログラムを更新します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
	
	fmt.Println(theTime.Format(time.RFC3339Nano))
}

事前定義された形式はstring値であり、目的の形式であるため、通常使用する形式をいずれかの形式に置き換える必要があります。

出力を確認するには、go runを使用してプログラムを再度実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-08-15T14:30:45.0000001-05:00

RFC 3339形式は、時間値をstringとしてどこかに保存する必要がある場合に使用すると便利です。 他の多くのプログラミング言語やアプリケーションで読み取ることができ、日付と時刻を柔軟なstring形式にすることができるのとほぼ同じくらいコンパクトです。

このセクションでは、Formatメソッドを使用して日付と時刻を出力するようにプログラムを更新しました。 この柔軟なレイアウトを使用すると、コードを最終出力のように見せることもできます。 最後に、事前定義されたレイアウト文字列の1つを使用して、十分にサポートされている形式を使用して日付と時刻を印刷しました。 次のセクションでは、プログラムを更新して、同じstring値を操作可能なtime.Time値に変換し直します。

文字列での日付と時刻の解析

多くの場合、アプリケーションを開発するときに、何らかの方法で解釈する必要があるstring値として表される日付に出くわします。 値の日付部分を知る必要がある場合もあれば、時間部分を知る必要がある場合もありますが、値全体が必要な場合もあります。 Formatメソッドを使用してtime.Time値からstring値を作成することに加えて、Gotimeパッケージは変換するtime.Parse関数を提供しますstringtime.Time値に変換します。 time.Parse関数は、Formatメソッドと同様に機能し、パラメーターとしてstring値だけでなく予想される日付と時刻のレイアウトも取ります。

次に、プログラムでmain.goファイルを開き、time.Parse関数を使用してtimeStringtime.Time変数に解析するように更新します。

projects / datetime / main.go
...

func main() {
	timeString := "2021-08-15 02:30:45"
	theTime, err := time.Parse("2006-01-02 03:04:05", timeString)
	if err != nil {
		fmt.Println("Could not parse time:", err)
	}
	fmt.Println("The time is", theTime)
	
	fmt.Println(theTime.Format(time.RFC3339Nano))
}

Formatメソッドとは異なり、time.Parseメソッドは、渡されたstring値が最初に提供されたレイアウトと一致しない場合に、潜在的なerror値も返します。パラメータ。 使用されているレイアウトを見ると、time.Parseに指定されたレイアウトは、同じ1を月に使用し、2を月の日に使用していることがわかります。 Formatメソッドで使用されます。

更新を保存した後、go runを使用して更新されたプログラムを実行できます。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 02:30:45 +0000 UTC 2021-08-15T02:30:45Z

この出力には、注意すべき点がいくつかあります。 1つは、timeStringから解析されるタイムゾーンが、+0オフセットであり、協定世界時(UTC)として知られるデフォルトのタイムゾーンを使用していることです。 時間値もレイアウトにもタイムゾーンが含まれていないため、time.Parse関数は、どのタイムゾーンに関連付けるかを認識していません。 ただし、ある時点で必要になった場合は、timeパッケージにtime.ParseInLocation 関数が含まれているため、使用する場所を指定できます。 注意すべき他の部分はRFC3339出力にあります。 出力はtime.RFC3339Nanoレイアウトを使用していますが、出力にはナノ秒が含まれていません。 これは、time.Parse関数がナノ秒を解析していないため、値がデフォルトの0に設定されているためです。 ナノ秒が0の場合、time.RFC3339Nano形式では出力にナノ秒が含まれません。

time.Parseメソッドは、string値を解析するときに、timeパッケージで提供される事前定義された時間レイアウトのいずれかを使用することもできます。 これを実際に確認するには、main.goファイルを開き、timeString値を更新して、以前のtime.RFC3339Nanoからの出力と一致させ、time.Parseパラメーターを更新して一致させます。 :

projects / datetime / main.go
...

func main() {
	timeString := "2021-08-15T14:30:45.0000001-05:00"
	theTime, err := time.Parse(time.RFC3339Nano, timeString)
	if err != nil {
		fmt.Println("Could not parse time:", err)
	}
	fmt.Println("The time is", theTime)
	
	fmt.Println(theTime.Format(time.RFC3339Nano))
}

コードを更新したら、プログラムを保存して、go runを使用して再度実行できます。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-08-15T14:30:45.0000001-05:00

今回は、Formatメソッドからの出力は、time.ParsetimeStringからのタイムゾーンとナノ秒の両方を解析できたことを示しています。

このセクションでは、time.Parse関数を使用して、任意の形式の日付と時刻の文字列値と事前定義されたレイアウトを解析しました。 ただし、これまでのところ、これまでに見たさまざまなタイムゾーンを操作していません。 Goがtime.Timeタイプに提供する別の機能セットは、次のセクションで説明するように、異なるタイムゾーン間で変換する機能です。

タイムゾーンの操作

世界中のユーザー、または少数のタイムゾーンのみでアプリケーションを開発する場合、一般的な方法は、協定世界時(UTC)を使用して日付と時刻を保存し、次の場合にユーザーの現地時間に変換することです。必要。 これにより、データを一貫した形式で保存でき、ユーザーに日付と時刻を表示する場合にのみ変換が必要になるため、データ間の計算が容易になります。

このチュートリアルの前のセクションでは、主に独自のローカルタイムゾーンに基づく時間に基づいて動作するプログラムを作成しました。 time.Time値をUTCとして保存するには、最初にそれらをUTCに変換する必要があります。 これは、UTCメソッドを使用して行います。このメソッドは、呼び出した時刻のコピーをUTCで返します。

注:このセクションでは、コンピューターのローカルタイムゾーンとUTCの間の時刻を変換します。 使用しているコンピューターのローカルタイムゾーンがUTCと一致するものに設定されている場合、UTCとその逆の変換では時間の違いが表示されないことに気付くでしょう。

次に、main.goファイルを開いてプログラムを更新し、theTimeUTCメソッドを使用して時刻のUTCバージョンを返します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
	fmt.Println(theTime.Format(time.RFC3339Nano))
	
	utcTime := theTime.UTC()
	fmt.Println("The UTC time is", utcTime)
	fmt.Println(utcTime.Format(time.RFC3339Nano))
}

今回は、プログラムがローカルタイムゾーンにtime.Time値としてtheTimeを作成し、2つの異なる形式で出力してから、UTCメソッドを使用してその時間を現地時間からUTC時間。

プログラムからの出力を確認するには、go runを使用して実行できます。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-08-15T14:30:45.0000001-05:00 The UTC time is 2021-08-15 19:30:45.0000001 +0000 UTC 2021-08-15T19:30:45.0000001Z

出力はローカルタイムゾーンによって異なりますが、上記の出力では、最初に印刷されるのはCDT(北米中部夏時間)である[であることがわかります。 X201X]UTCからの時間。 UTCメソッドが呼び出され、UTC時刻が出力されると、時刻をUTCに変換すると5時間が追加されるため、時刻が14から19に変わることがわかります。 。

同様に、time.TimeLocalメソッドを使用して、UTC時刻を現地時間に戻すこともできます。 main.goファイルを再度開き、更新してutcTimeLocalメソッドへの呼び出しを追加し、ローカルタイムゾーンに変換し直します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
	fmt.Println(theTime.Format(time.RFC3339Nano))
	
	utcTime := theTime.UTC()
	fmt.Println("The UTC time is", utcTime)
	fmt.Println(utcTime.Format(time.RFC3339Nano))

	localTime := utcTime.Local()
	fmt.Println("The Local time is", localTime)
	fmt.Println(localTime.Format(time.RFC3339Nano))
}

ファイルが保存されたら、go runを使用してプログラムを実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-08-15T14:30:45.0000001-05:00 The UTC time is 2021-08-15 19:30:45.0000001 +0000 UTC 2021-08-15T19:30:45.0000001Z The Local time is 2021-08-15 14:30:45.0000001 -0500 CDT 2021-08-15T14:30:45.0000001-05:00

UTC時刻がローカルタイムゾーンに変換されていることがわかります。 上記の出力では、UTCからCDTへの変換は、UTCから5時間が差し引かれ、時間を19から14に変更したことを意味します。

このセクションでは、UTCメソッドを使用して、ローカルタイムゾーンと標準UTCタイムゾーンの間で日付と時刻を変換し、Localメソッドを使用して、プログラムを更新しました。

日付と時刻の値を利用できるようになると、Go timeパッケージが提供する、アプリケーションで役立つ追加機能がいくつかあります。 これらの機能の1つは、特定の時間が次の時間の前か後かを判断することです。

2回の比較

2つの日付を互いに比較することは、それらを比較するときに考慮する必要のあるすべての変数のために、一見難しい場合があります。 たとえば、タイムゾーンを考慮する必要がある、または月の日数が互いに異なるという事実。 timeパッケージは、これを簡単にするためのいくつかの方法を提供します。

timeパッケージは、これらの比較を容易にする2つのメソッドを提供します。BeforeメソッドとAfterメソッドで、time.Timeタイプで使用できます。 これらのメソッドは両方とも単一の時間値を受け入れ、呼び出されている時間が指定された時間の前か後かに応じて、trueまたはfalseのいずれかを返します。

これらの関数の動作例を確認するには、main.goファイルを開き、2つの異なる日付を含むように更新してから、BeforeAfterを使用してこれらの日付を比較し、出力:

projects / datetime / main.go
...

func main() {
	firstTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The first time is", firstTime)

	secondTime := time.Date(2021, 12, 25, 16, 40, 55, 200, time.UTC)
	fmt.Println("The second time is", secondTime)

	fmt.Println("First time before second?", firstTime.Before(secondTime))
	fmt.Println("First time after second?", firstTime.After(secondTime))

	fmt.Println("Second time before first?", secondTime.Before(firstTime))
	fmt.Println("Second time after first?", secondTime.After(firstTime))
}

ファイルを更新したら、ファイルを保存して、go runを使用して実行します。

  1. go run main.go

出力は次のようになります。

Output
The first time is 2021-08-15 14:30:45.0000001 +0000 UTC The second time is 2021-12-25 16:40:55.0000002 +0000 UTC First time before second? true First time after second? false Second time before first? false Second time after first? true

コードはUTCタイムゾーンで明示的な日付を使用しているため、出力は上記の出力と一致する必要があります。 firstTimeBeforeメソッドを使用し、比較するためにsecondTimeを提供すると、true[ X144X]は2021-12-25の前にあります。 firstTimeAfterメソッドを使用してsecondTimeを提供すると、2021-08-152021-12-25の後にあるのはfalseであると表示されます。 。 secondTimeのメソッドを呼び出す順序を変更すると、予想どおり、逆の結果が表示されます。

timeパッケージで2つの日付と時刻を比較する別の方法は、Subメソッドです。 Subメソッドは、ある日付を別の日付から減算し、新しいタイプtime.Durationを使用して値を返します。 絶対的な時点を表すtime.Time値とは異なり、time.Duration値は時間の差を表します。 たとえば、「1時間以内」は、現在の時刻に基づいて異なる意味を持つため、期間になりますが、「正午」は特定の絶対時間を表します。 Goは、time.Durationタイプをさまざまな場所で使用します。たとえば、関数がエラーを返すまでの待機時間を定義する場合や、1つの時間の間の時間を知る必要がある場合などです。と別の。

次に、main.goファイルを更新してfirstTimeおよびsecondTime値でSubメソッドを使用し、結果を出力します。

projects / datetime / main.go
...

func main() {
	firstTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The first time is", firstTime)

	secondTime := time.Date(2021, 12, 25, 16, 40, 55, 200, time.UTC)
	fmt.Println("The second time is", secondTime)

	fmt.Println("Duration between first and second time is", firstTime.Sub(secondTime))
	fmt.Println("Duration between second and first time is", secondTime.Sub(firstTime))

ファイルを保存し、go runを使用して実行します。

  1. go run main.go

出力は次のようになります。

Output
The first time is 2021-08-15 14:30:45.0000001 +0000 UTC The second time is 2021-12-25 16:40:55.0000002 +0000 UTC Duration between first and second time is -3170h10m10.0000001s Duration between second and first time is 3170h10m10.0000001s

上記の出力は、2つの日付の間に3,170時間、10分、10秒、および100ナノ秒があることを示しており、出力について注意すべき点がいくつかあります。 1つ目は、1回目と2回目の間の期間が負の値であるということです。 これは、2回目が1回目以降であり、0から5を引いて、-5を取得した場合と同様です。 2つ目の注意点は、期間の最大の測定単位は1時間であるため、日や月に分割されないことです。 1か月の日数には一貫性がなく、夏時間の切り替え時に「日」の意味が異なる可能性があるため、変動しない最も正確な測定値は1時間です。

このセクションでは、3つの異なる方法を使用して2回比較するようにプログラムを更新しました。 最初に、BeforeおよびAfterメソッドを使用して、ある時間が別の時間の前後かどうかを判断し、次にSubを使用して2つの時間の間の長さを確認しました。 ただし、timeパッケージがtime.Durationを使用する方法は、2つの時間の間の期間を取得することだけではありません。 次のセクションで説明するように、これを使用してtime.Time値に時間を追加または削除することもできます。

時間の加算または減算

アプリケーションを作成する場合、日付と時刻を使用する一般的な操作の1つは、別の時刻に基づいて過去または未来の時刻を決定することです。 これは、サブスクリプションが次に更新される時期を決定したり、値がチェックされてから一定の時間が経過したかどうかを判断するなどの機能に使用できます。 いずれにせよ、Gotimeパッケージはそれを処理する方法を提供します。 ただし、すでに知っている日付に基づいて別の日付を見つけるには、独自のtime.Duration値を定義できる必要があります。

time.Duration値の作成は、時間の単位を乗算するだけで、紙に期間を書き込む方法と似ています。 たとえば、1時間を表すtime.Durationを作成するには、time.Hourの値にtime.Durationで表す時間数を掛けて定義します。

oneHour := 1 * time.Hour
twoHours := 2 * time.Hour
tenHours := 10 * time.Hour

time.Minutetime.Secondなどを使用することを除いて、より小さな時間単位の宣言も同様の方法で処理されます。

tenMinutes := 10 * time.Minute
fiveSeconds := 5 * time.Second

ある期間を別の期間に追加して、期間の合計を取得することもできます。 これが実際に動作することを確認するには、main.goファイルを開き、それを更新してtoAdd期間変数を宣言し、それに異なる期間を追加します。

projects / datetime / main.go
...

func main() {
	toAdd := 1 * time.Hour
	fmt.Println("1:", toAdd)

	toAdd += 1 * time.Minute
	fmt.Println("2:", toAdd)

	toAdd += 1 * time.Second
	fmt.Println("3:", toAdd)
}

更新が完了したら、ファイルを保存し、go runを使用してプログラムを実行します。

  1. go run main.go

出力は次のようになります。

Output
1: 1h0m0s 2: 1h1m0s 3: 1h1m1s

出力を見ると、最初に印刷される期間は1時間であり、コードの1 * time.Hourに対応していることがわかります。 次に、1 * time.MinutetoAddの値に追加しました。これは、1時間1分の値として表示されます。 最後に、1 * time.SecondtoAddに追加しました。これにより、time.Durationの値は1時間、1分、1秒になります。

1つのステートメントで期間を合計したり、別のステートメントから期間を減算したりすることもできます。

oneHourOneMinute := 1 * time.Hour + 1 * time.Minute
tenMinutes := 1 * time.Hour - 50 * time.Minute

次に、main.goファイルを開き、プログラムを更新して、次のような組み合わせを使用して、toAddから1分1秒を減算します。

projects / datetime / main.go
...

func main() {
	
	...
	
	toAdd += 1 * time.Second
	fmt.Println("3:", toAdd)
	
	toAdd -= 1*time.Minute + 1*time.Second
	fmt.Println("4:", toAdd)
}

コードを保存した後、go runを使用してプログラムを実行できます。

  1. go run main.go

出力は次のようになります。

Output
1: 1h0m0s 2: 1h1m0s 3: 1h1m1s 4: 1h0m0s

出力に追加された新しい4行目は、1 * time.Minute1 * time.Secondの合計を差し引くために含めた新しいコードを示しており、元の1時間の値になります。

これらの期間をtime.TimeタイプのAddメソッドと組み合わせて使用すると、すでに持っている時間値を取得し、その時間の前後の他の任意の時点で時間を決定できます。 この実行例を確認するには、main.goファイルを開き、toAdd値を24時間、または24 * time.Hourに設定するように更新します。 次に、time.Time値に対してAddメソッドを使用して、その時点から24時間後の時刻を確認します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The time is", theTime)

	toAdd := 24 * time.Hour
	fmt.Println("Adding", toAdd)

	newTime := theTime.Add(toAdd)
	fmt.Println("The new time is", newTime)
}

ファイルを保存した後、go runを使用してプログラムを実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 +0000 UTC Adding 24h0m0s The new time is 2021-08-16 14:30:45.0000001 +0000 UTC

出力を見ると、2021-08-15に24時間を追加すると、2021-08-16の新しい日付になることがわかります。

時間を差し引くには、Addメソッドも使用しますが、これは少し直感に反します。 Subメソッドは、2つの日付間の時間の差を取得するために使用されるため、負の値のAddを使用して、time.Time値から時間を減算します。

もう一度、これがプログラムで実行されていることを確認するには、main.goファイルを開いて更新し、24時間のtoAdd値を負の値に変更します。

projects / datetime / main.go
...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The time is", theTime)

	toAdd := -24 * time.Hour
	fmt.Println("Adding", toAdd)

	newTime := theTime.Add(toAdd)
	fmt.Println("The new time is", newTime)
}

ファイルを保存した後、go runを使用してプログラムをもう一度実行します。

  1. go run main.go

出力は次のようになります。

Output
The time is 2021-08-15 14:30:45.0000001 +0000 UTC Adding -24h0m0s The new time is 2021-08-14 14:30:45.0000001 +0000 UTC

今回の出力では、元の時刻に24時間を追加する代わりに、新しい日付が元の時刻の24時間前になっていることがわかります。

このセクションでは、time.Hourtime.Minute、およびtime.Secondを使用して、さまざまな次数のtime.Duration値を作成しました。 また、time.Duration値をAddメソッドとともに使用して、元の値の前後の両方で新しいtime.Time値を取得しました。 time.NowAddメソッド、およびBeforeまたはAfterメソッドを組み合わせることで、アプリケーションの強力な日付と時刻の機能にアクセスできます。

結論

このチュートリアルでは、time.Nowを使用して、コンピューターの現在の現地時間のtime.Time値を取得してから、YearMonthHour、およびその時間に関する特定の情報にアクセスするための他の方法。 次に、Formatメソッドを使用して、カスタム形式と事前定義された形式を使用して時刻を印刷しました。 次に、time.Parse関数を使用して、時刻を含むstring値を解釈し、そこから時刻値を抽出しました。 時間値を取得したら、UTCおよびLocalメソッドを使用して、UTCとローカルタイムゾーンの間の時間を変換しました。 その後、Subメソッドを使用して、2つの異なる時間の間の期間を取得してから、Addメソッドを使用して、異なる時間値に関連する時間を検索しました。

このチュートリアルで説明されているさまざまな関数とメソッドを使用すると、アプリケーションで大いに役立ちますが、興味がある場合は、Go timeパッケージに他の多くの機能も含まれています。

このチュートリアルは、 DigitalOcean How to Code inGoシリーズの一部でもあります。 このシリーズでは、Goの初めてのインストールから、言語自体の使用方法まで、Goに関する多くのトピックを取り上げています。