OmniAICreator/Qiita-1.07M huggingface dataset:
オーディオレイヤーのアウト点に向かってボリュームフェードアウトするエクスプレッション

## TL;DR
いちいちキーフレーム打つのめんどくさいなと思って作りました。

エクスプレッション
```
//アウト点の何秒前からフェードアウト開始するか
fadeTime = 2;
//アウト点のボリュームレベル（ステレオLR）
endVol = [-48, -48];

startVol = thisComp.layer(index).audio.audioLevels.valueAtTime(outPoint - fadeTime);
linear(time, outPoint - fadeTime, outPoint, startVol, endVol);
```
使い方はこんな感じです。
![2023-04-06 01_43_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154859/b54f3385-d5ca-9114-64c9-70c1481520e6.png)

### おわりに
ワークエリアのイン・アウトに対応するのもアリかもしれない
RubyでAtCoder ABC288(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC288のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Many A+B Problems
https://atcoder.jp/contests/abc288/tasks/abc288_a
```ruby:a-288.rb
n = gets.to_i
n.times do
    puts gets.split.map(&:to_i).sum
end
```
## 解説
問題文の通りに実装するだけです。

# B - Qualification Contest
https://atcoder.jp/contests/abc288/tasks/abc288_b
```ruby:b-288.rb
n, k = gets.split.map(&:to_i)
array = Array.new(n){ gets.chomp }
puts array[0, k].sort
```
## 解説
sortを使って、辞書順にした後の上位K人のハンドルネームを出力すればOKです。

# C - Don’t be cycle
https://atcoder.jp/contests/abc288/tasks/abc288_c
```ruby:c-288.rb
n, m = gets.split.map(&:to_i)

array = Array.new(n + 1){[]}
m.times do
    a, b = gets.split.map(&:to_i)
    array[a] << b
    array[b] << a
end

searched = Array.new(n + 1, false)
count = 0
for i in 1..n
    next if searched[i]
    count += 1
    stack = [i]
    searched[i] = true
    while node = stack.pop
        array[node].each do|i|
            next if searched[i]
            searched[i] = true
            stack << i
        end
    end
end
puts m - (n - count)
```
## 解説
<方針と実装方法>
連結成分が閉路とならないためには、(辺の数)=(頂点の数)-1となればいいことがわかります。また、最終的な頂点の数はN個であることがわかっています。以上のことから、最終的な辺の数がN-(連結成分の数)となればすべての連結成分は閉路でないということになります。したがって、答えはM個ある辺をN-(連結成分の数)とするために削除した辺の数(= M-N-(連結成分の数))となります。

なお、連結成分の探索は、292のD問題のときと同様にスタックを使ったDFSで行なっています。

# 終わりに
今回の問題は、A問題とB問題が比較的簡単で、C問題は考えていて面白かったです。
次回は、AtCoder ABC287を解いていきたいと思います。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
Goのhtml/templateやGinでコメント文を削除させずに出力させたい時

# はじめに
よくあるWebサイトのhtmlを覗くとコメント文が書いてあることがよくあります。
ですが、Goで書いたWebサーバーはテンプレートを通すとコメント文がすべからく削除されます。

ブラウザ上では基本的に見ることは無いので高速化するのに助かる機能ですが....

他のWebサーバーで存在するのにGoには無いのが気持ち悪いのでコメントアウトを記述できるようにします(~~隠しAA書けないし~~

↓テンプレートに使うファイル
```templates/index.html
<!DOCTYPE html>
<html>
    <head></head>
    <body>
    (適当な内容)
    {{"<!-- 適当なコメント -->"　| safeHTML}}
    <!-- safeHTMLはgoで指定する任意の関数の名前 -->
    </body>
</html>
```

# html/templateのみの場合
```main.go
package main

import(
    "html/template"
    "log"
	"net/http"
)

func main() {
    // ハンドラを指定
    http.HandleFunc("/", TopPage)
    // 80番ポートで鯖立て
    log.Fatal(http.ListenAndServe(":80", nil))
}

// index.htmlのハンドラ関数
func TopPage(w http.ResponseWriter, r *http.Request){
    fileDir := "templates/"        // htmlのディレクトリ
    fileName := "index.html"  // ファイル名
    data := nil // テンプレートに渡す構造体

    // テンプレートで使用する関数マップ
	funcMap := template.FuncMap{
        // ここでテンプレートの関数に文字列を生のhtmlとして描画する関数を登録する(名前は任意でよい)
		"safeHTML": func(text string) template.HTML { return template.HTML(text) },
	}

    // テンプレートを描画
    t := template.Must(template.New(fileName).Funcs(funcMap).ParseFiles(fileDir + fileName))
	if err := t.Execute(w, data); err != nil {
    	log.Println(err)
	}

}
```

# Ginを使った場合
自分はginを使った方が楽です
```main.go
package main

import(
    "html/template"
    "log"
	"net/http"
    "github.com/gin-gonic/gin"
)

func main() {
    
    router := gin.Default()

    // ここでテンプレートの関数に文字列を生のhtmlとして描画する関数を登録する(名前は任意でよい)
    // routerで指定するハンドラ全部に反映されるので良き
    router.FuncMap["safeHTML"] = func(text string) template.HTML { return template.HTML(text) }

    // ファイルを事前にロード
	router.LoadHTMLGlob("templates/*")

    // ハンドラを指定
    router.GET("/",TopPage)

    // 80番ポートで鯖立て
    log.Fatal(http.ListenAndServe(":80", router))
}

// index.htmlのハンドラ関数
func TopPage(c *gin.Context){
	c.HTML(http.StatusOK, "index.html", nil)
}
```

# 結果
こんな感じの出力になります
```
<!DOCTYPE html>
<html>
    <head></head>
    <body>
    (適当な内容)
    <!-- 適当なコメント -->
    </body>
</html>
```
Kaggle notebookとGoogle Colabのデータ連携

Kaggle notebook上で作業していると、時々インポートしたライブラリ内で発生したエラーに遭遇する。これは必ずしもライブラリ内の実装に問題があるわけではなく、自分の書いたコードに問題があることが多い。しかし、デバッグする上ではライブラリの中のコードにコメントアウトを挟み込むことで原因を究明することが有効なこともある。このような場合、Kaggle notebook上ではファイルを編集することは非常に手間である。

ライブラリ内のファイルを編集しながらデバッグするには、ローカルのマシンを使うのが最も簡単ではあるが、Kaggleと似たような環境でデバッグを行うにはGoogle Colabを使うのが便利である。Google ColabではKaggleと同様にGPUを使うこともできるので、GPUとのデータのやり取りに関する部分のデバッグも行うことができる。

で、問題となるのはそれぞれのプラットフォーム間でのデータ連携であり、今回はこちらについてメモを残すことにする。



### Kaggle -> Google Colab

KaggleのデータにGoogle Colabからアクセスするには、Kaggleで発行したアクセスキーを読み込み、Colabからデータにアクセス、コピーすることで行う。

まずはKaggleの自分のAccountページに移動し、'Create New API Token'を押してトークン'kaggle.json'をダウンロードする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/cd07e8c5-f0aa-fef4-84f5-377cfae8ff15.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/94b489e3-3000-dd4b-5d1c-2dfab5faae3c.png)

ダウンロードしたトークンをgoogle driveにアップロードする。以下、トークンを'My Drive'配下に格納した場合を書く。

Google Colab notebookに移動し、まずはGoogle DriveをColabのデータとしてマウントする。以下の例では、Colabの'/content/drive/'上にgoogle driveのMy Driveがマウントされ、'/content/drive/MyDrive'が生成される。

```python
from google.colab import drive
drive.mount('/content/drive')
```

続いて、下記コマンドを実行する。

```python
import os
import json
f = open("/content/drive/MyDrive/kaggle.json")
json_data = json.load(f)
os.environ['KAGGLE_USERNAME'] = json_data['username']
os.environ['KAGGLE_KEY'] = json_data['key']
```

あとはKaggle用のパッケージをインストールすれば、アクセスが可能になる。

```
!pip install kaggle
```

データのダウンロード手順は次のようにする。まずはデータがあるページまで移動する。下の方に行くと、APIコマンドが書いてあるのでコピーする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/a2e55b38-5bda-87c0-d727-07d625ba408c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/58510e57-36ca-9dc9-33f7-e4061ee2b6b9.png)

Google Colab notebookに戻り、こちらをペーストして実行する。

```
!kaggle competitions download -c siim-covid19-detection
```

データは80G超なので途中でストップした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/af900cea-c866-5843-85a6-b5b3cb235d89.png)


コンペのデータは大容量なので、データを使ったテストはKaggle notebook上で行い、データの一部を使った実験や、他の方が提供している改造版のパッケージを試すときなどは、上記の方法でGoogleにもってきてテストするようにしている。




### Google Colab -> Kaggle 

残念ながら、私の調べた限りGoogle ColabからKaggleへ直接データを移す手段は見つからなかった。そのため、Google Colabから一度データをダウンロードし、KaggleのDatasetとしてアップロードし、notebookからそのDatasetを追加することで使うようにしている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/794eea1f-08e3-c41a-0c64-43b2d5436b18.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514778/e2a7b4fb-0aef-0719-89ca-3a8c571f87a7.png)

なお、データはzipやtar.bzで圧縮してアップロードすることが推奨されており、アップロードされたデータのうち、圧縮ファイルと認識されたものは自動的に解凍される。tar.bzなどはそのまま使いたいときもあるので、便利なようで不便なのかもしれない。
ChatGPTで自作の3Dキャラ（VRM）におしゃべりしてもらう体験をする

ChatGPTを利用して、VRMにしゃべってもらうWindowsアプリを作りました。
VRoidStudioを利用して作った3Dキャラクターが、自分の質問に答えてくれています。

https://twitter.com/machidyo/status/1643641557302771713?s=20

VRMの3Dキャラクターを入れ替えることで、自分の作った3Dキャラクターで体験できるようになっています。良かったら試してみてください。リポジトリは[こちら](https://github.com/machidyo/speaking-vrm-with-chatgpt-sample/blob/master/README.md)です。

# 前提
* Windows10（音声入力がWindowsでかつ１０が前提で、Windows11では動きません）
* Unity 2021.2.4f1
* VRM

## 注意
* voicevox_engineは含まれていません（使い方を参照しくてください）
* 動画の背景は有料Assetなので含まれていません

# 使い方
1. OpenAIのAPIKeyを作成して、SampleSceneにいるTesterのInspectorのApi Keyに設定します
2. voicevox_engineをdockerで起動します（※1）
3. Unityを実行して、ConsoleにStart speech recognition, waiting for your voice...と出てきていることを確認します
4. 話しかけてください！ドレが回答してくれるはずです。

※1
dockerでなくても大丈夫で、[こちら](https://voicevox.hiroshiba.jp/)で代替できる、はずです。GUIを起動するだけ内部的にvoicevox_engineが起動されるため、それを利用できる、はずです。（どなたか試した方がいたら教えていただけると幸いです。）

## 注意
* ときどき音声認識がうまく反応しないときがあります。その場合、再実行してみてください。

# VRMの入れ替え方
1. vrmをドラッグアンドロップでインポートします。
2. 1でインポートしたvrmをHierachyに配置します。
3. doreのPositionをコピーして、カメラ位置まで移動させます。
4. おそらく後ろを向いているのでY軸で180度回転させます。（doreのrotation参照）
5. doreを削除します。

# 動画の補足
1. Unityを実行すると、音声入力待ちの状態になります。（上記動画では"塩の作り方を教えてください"といった後です）
2. 音声入力が完了すると、テキストで画面下に表示されます。（上記動画の"塩の作り方を教えてください"の箇所です）
3. 2に続いて、ChatGPTへテキストを基にリクエストを出してレスポンスを待ちます。（回答内容によって10秒ほどかかることがあります）
4. ChatGPTからレスポンスが返ってくると、その内容をVOICEVOXに連携して音声合成を待ちます。（
5. 音声合成が完了すると、VRMのBlendshapeとOVRLipSyncを利用してVRMのアバターがしゃべりだしてくれます。（上記動画はこの5からです）

# 使っているOSS
Library     |  License
------------|------------
[unity-voicevox-bridge](https://github.com/mikito/unity-voicevox-bridge)                    | MIT license
[voicevox_engine](https://github.com/VOICEVOX/voicevox_engine)                              | Unknown, LGPL-3.0 licenses found
[VRMLipSyncContextMorphTarget](https://github.com/TsubokuLab/VRMLipSyncContextMorphTarget)  | Unknown,
[UniVRM](https://github.com/vrm-c/UniVRM)                                                   | MIT license
[UniTask](https://github.com/Cysharp/UniTask)                                               | MIT license

# 参考にしたサイト
* [ChatGPT APIをUnityから動かす。](https://note.com/negipoyoc/n/n88189e590ac3)
* [GPT-3とVoiceVoxを活用してAIエージェントを作る！【Unity】](https://note.com/negipoyoc/n/n081e25f5ee9e)
* [VOICEVOX(音声合成)をREST-APIで利用する](https://qiita.com/A_T_B/items/1531d78944d8b796b9fa)
新しい Bingで「日本語プログラミング言語」「説明する」を選んだら‘日本語プログラミング言語 普及しない 理由’ を検索し始めた

# はじめに
Edgeで[「日本語プログラミング言語は 日本人にとって可読性が高いが、 なぜあまり普及していないのか」という学生さんの卒論に感銘をうけたお話](https://qiita.com/mylifewithviolin/items/d15fdf16c6a66bdcf5b1)という記事のタイトルから「日本語プログラミング言語」を選択して右クリックすると「検索」ポップアップが出るのでそれをクリックすると、右側に「新しい Bing」がしゃしゃりでてくるので、「日本語プログラミング言語」を貼り付け「説明する」を実行してみました。

## この記事内容の作業環境
Windows11
Microsoft Edge 111.0.1661.41

## この記事内容の保証
※この記事にはAIが自動生成した意見的な情報が含まれます。AIが自動生成して書かれた内容の妥当性は必ずしも保証されません。

# 実行結果

ページから貼り付け済み
日本語プログラミング言語

テキストに対する処理を選択してください。
説明する

ページから貼り付け済み
日本語プログラミング言語

テキストに対する処理を選択してください。
説明する

‘日本語プログラミング言語 普及しない 理由’ を検索しています

‘日本語プログラミング言語 普及率’ を検索しています

回答を生成しています…

「日本語プログラミング言語」は、日本人にとって可読性が高いとされていますが、普及率が低い理由は複数あります。一つは、英語圏で開発されたプログラミング言語が世界的に普及しているため、日本語プログラミング言語を学ぶことで得られるメリットが少ないと考えられていることです。また、日本語プログラミング言語を学ぶことで得られるスキルが、英語圏での就職にはあまり役立たないことも理由の一つです。[1](https://qiita.com/mylifewithviolin/items/d15fdf16c6a66bdcf5b1) [2](https://halo.aichi-u.ac.jp/wp/wp-content/uploads/2021/10/5fca7c3a7df99c6d0e24a2f840fad199.pdf)

ただし、教育分野では「なでしこ」「プロデル」「ドリトル」などの日本語プログラミング言語が使用されており、教育目的に開発された「ドリトル」の方がプログラム経験者が読みやすいという感想をもつのは、自然日本語に近い構文の前２者より英語系一般的プログラム言語の構文に近いせいではないか、そこに日本語プログラミング言語の普及のカギがあるのではと、結論づけられています。[1](https://qiita.com/mylifewithviolin/items/d15fdf16c6a66bdcf5b1) 

1: [日本語プログラミング言語は 日本人にとって可読性が高いが、 なぜあまり普及していないのか](https://qiita.com/mylifewithviolin/items/d15fdf16c6a66bdcf5b1)  2:日本人向けプログラミング言語「なでしこ」を使ってみた


詳細情報:
1. [qiita.com](https://qiita.com/mylifewithviolin/items/d15fdf16c6a66bdcf5b1)
2. [halo.aichi-u.ac.jp](https://halo.aichi-u.ac.jp/wp/wp-content/uploads/2021/10/5fca7c3a7df99c6d0e24a2f840fad199.pdf)
3. [sejuku.net](https://www.sejuku.net/blog/143373)
4. [xtech.nikkei.com](https://xtech.nikkei.com/atcl/nxt/mag/nc/18/072100242/072100001/)
5. [ja.wikipedia.org](https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E)
— 表示を減らす

# 考察
実際に開いていたページの内容を認識したのか、それとは無関係に検索した結果がたまたまそうだったのか、ちょっと判別つけがたいところではありますが、[「日本語プログラミング言語は 日本人にとって可読性が高いが、 なぜあまり普及していないのか」という学生さんの卒論に感銘をうけたお話](https://qiita.com/mylifewithviolin/items/d15fdf16c6a66bdcf5b1)という記事を引用してまとめてきたのにはびっくりしました。

１小節目の文章はかなり練られている感はありますが、２小節目の文章は引用記事の下記の文を多少加工した感は否めないです。

>論文では多目的用途に開発された「なでしこ」「プロデル」よりも教育目的に開発された「ドリトル」のがプログラム経験者が読みやすいという感想をもつのは、自然日本語に近い構文の前２者より英語系一般的プログラム言語の構文に近いせいではないか、そこに日本語プログラミング言語の普及のカギがあるのではと、結論づけられているように読み取れました。（あくまで筆者の解釈とイメージです。）論者は「ミスマッチ」と表現しています。

ちなみに　「普及しない」「理由」「普及率」といったワードをくっつけてきたのは、いま開いているページの内容を汲み取ったかもしれないです。

「なでしこ」を使ってみた　の生成リンクは変だったので割愛しました。

日本語トークン使用言語に関わらず、「プログラミング言語を学ぶことで得られるスキル」の本質とは、といった点についても対話してみたくなりました。そのあたりの認識が弱いとはやりの実装言語にふりまわされることになるので気をつけましょう。

# おわりに
次回、まったく無関係なページを開いて実行して、再現性を検証してみます。

# 2023/04/08 追記
Edgeの新しいタブで一般的なニュース記事がたくさん表示されているページを開いた状態で、「日本語プログラミング言語」で「説明する」を選択した場合は特に忖度した動きとはならず、一般的に検索した結果をテキストでまとめる感じでした。

# 参考リンク
https://qiita.com/mylifewithviolin/items/9d58db8a101807c19bde

https://qiita.com/mylifewithviolin/items/9214582528edcbd606ad

https://qiita.com/mylifewithviolin/items/52f806777e6ea031de94
GitHub pushまでの流れ 

４月からエンジニアとして働いています。
現在は研修中で、研修内容では`AWS`で`codecommit`というものを使っています。

メンターに何度も指摘を受けているのに、プルリクエストで修正が入るため自己学習として`GitHub`の`push`までの流れをまとめます。

プログラミング初学者と自分の成長につながればと思います。


### ファイルに変更を加えたら、、

まずは変更内容を確認します。
理由は変更した内容以外に、意図していない変更が起きていないか確認するためです。
私の場合は身に覚えのないのに、ファイルが削除されていたり、タスクと関係のないファイルに編集した痕跡があり、メンターに指導されました。

自分の変更内容を確認するコマンドは以下です
```
git status
```
このコマンドは`ワーキングツリー`の状態と、`ステージング`の状態を表示する`コマンド`です。
`ワーキングツリー`というのは現在作業している領域です。
`ステージング`とは`コミット`を待っている一時保存領域のような場所です。

`git status`をたたき、作業したファイルと表示されている`ファイル`に相違がないこと確認できたら以下の`コマンド`を入力しましょう。

```
git add .
```
このコマンドは先ほどお伝えした、`ワーキングツリー`から`ステージングエリア`へ編集内容を一時保存（`コミット`を待機）する`コマンド`です。一番最後の.(`conma`)は全ての`ファイル`を指名しています。

### ここでさらに
変更内容をステージングエリアへ加えたら、やっとここで`ローカルリポジトリ`へ保存する`コマンド`を叩きます。
```
git commit -m "変更内容を誰が見ても分かるようにかつ、コンパクトに記載する"
```
これを何度か繰り返し機能などを記述していきましょう。

そして前回の`コミット`との差をみておきましょう。正しい変更内容か確認するためです。
時々、必要な`ファイル`が作成されていなかったり、よくわからない`ファイル`が作成されていることがあるからです。
前回の`コミット`との差を確認する`コマンド`は以下です。
```
git diff
```
`ローカルリポジトリ`の内容を`リモートリポジトリ`へ送りたいところですが、まだです。

私が良くあった`ミス`、というか反省は`プッシュ`した後の`コンフリクト`です。
これが起こると、複数人規模の開発ではどえらいことになるそうです。
なのでまずは`リモートリポジトリ`にある最新の状態を今の自分の変更内容へ引っ張ってきて、`コンフリクト`を解消しておきましょう。
```
git pull origin ブランチ名
```
これで自分のパソコンである程度小規模の`コンフリクト`を発生・解消します。

そして、ようやく`push`します。

すごく面倒で手間だと最初は感じますが、だんだんとこの作業のおかげでタイムロスを防げることを実感できてきます。一緒に頑張っていきましょう。
LamdaとCloudWatch Eventsでnode.js 18を定期実行する

# 目的

API連携をしてみたくて何作るかchatGPTと話していたら、
いつの間にか今日はLamdaとCloudWatch Eventsでnode.js 18を定期実行してみることになりました。
AWSとnode.jsはどっちも初めてなので勉強しながら備忘録！


# 今回やること

今回の目標は以下の2つ。
1. Lamdaでnode.jsのコードを実行してみる
1. CloudWatch Eventsで定期実行する


# 環境
* windows 10
* node.js 18
* リージョン 東京


# いざ出陣

### AWSアカウントの発行

ここからAWSアカウントを作成します。

https://portal.aws.amazon.com/billing/signup#/start/email

英語ですが画面見ながら手順に進めると作成できました。
英語で住所書くときの順番が覚えられないのですが、chatGPTに

> 「自分の住所」を英語で書きたい。
> Address、City、State, Province, or Region、Postal Codeに分けて書いて。

とか聞いて教えてもらいました。神。

### LambdaでHello World!

これ見ながらやります。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/getting-started.html

Lambdaの設定項目は以下の通り
<dl>
  <dt>オプション</dt>
  <dd>一から作成</dd>
  <dt>関数名</dt>
  <dd>HelloWorld</dd>
  <dt>ランタイム</dt>
  <dd>Node.js 18.x</dd>
  <dt>アーキテクチャ</dt>
  <dd>x86_64</dd>
</dl>

```javascript:index.mjs
export const handler = async(event) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
    };
    return response;
};
```

ルールを作成する前に、適当にテストイベントを設定して実行してみたら「Excution results」の「Response」に結果が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/38b15151-f526-6f86-8491-b2c02a6c3bea.png)


### CloudWatchで定期実行

ルールを作成 > スケジュールから実行スケジュールを設定します。
スケジュールを選ぶと、「Amazon EventBridge」に飛ばされます。
調べてみたら「Amazon EventBridge」は「CloudWatch Events発展版のサービス」みたいな感じらしいです。
詳しいことは後で。

実行時間を設定する「corn」は最近やったので何かは分かってました。
以下を入力して、日本時間で毎日00:10に設定します。
タイムゾーンは、OSのタイムゾーン設定で決まるようなので気にせず日本時間で入力しました。

```:cron
corn(10 0 * * ? *)
```

ターゲットに先ほど作成したLmbda関数が表示されない場合、右上のリージョンが一致しているか確認してください。
僕は、それで困りました...

ルールを設定したら、cronで入力した時間に実行されるはずです。
CloudWatch > ログ > ロググループから、ロググループを選択して実行を確認できます。
「Hello World!」がどこに出るかは分からなかったですが...
多分、出ないんでしょう。終わり！


# 余談
そういえば、料金のこと考えていませんでした。
以下のサイトで無料枠を確認できます。

https://aws.amazon.com/jp/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all

無料枠は以下の通りです。
> 1,000,000 件/月の無料リクエスト
> 1 か月あたり最大 320 万秒のコンピューティング時間

なんか大丈夫そうですね。
一応、ルールと関数は削除しときます。
次は本来の目的であるAPI連携のコード実行します！
【RaspberryPi+Python】pingを利用してAndroid機器の死活監視をする

# 概要
ラズベリーパイから監視対象（今回Android端末）へpingを送信してタイムアウトすれば障害発生、通れば正常という判定をします。
今回は5秒おきにpingを送信し、これが5回連続で失敗した場合は障害としてLINE NOTIFYに通知を送るようにします。

# 作成したきっかけ
とあるスマホゲームで自動操作をさせているときにたまにOSの再起動が発生して自動操作が止まってしまっていたため、そのときは携帯電話に通知がしたいなと思いました。
ラズベリーパイを選んだのは省電力で動作することやPythonがデフォルトで搭載されているのでこれが良いのかなという考えからです。

# 使った物品
- Raspberry Pi 3b

# 準備
- LINE NOTIFYのAPIアクセストークン発行
- Python用の必要なライブラリのインストール
```
sudo pip install pings
sudo pip install requests
```

# コード
```ping_monitoring.py
import pings
import requests
import time
import datetime

def line(message):
	line_access_token = 'アクセストークン'
	line_url = "https://notify-api.line.me/api/notify"
	line_headers = {"Authorization" : "Bearer "+ line_access_token}
	line_message =  message
	line_payload = {"message" : line_message}
	requests.post(line_url ,headers = line_headers ,params=line_payload)
        
def send_ping(ipaddr):
    p = pings.Ping()
    res = p.ping(ipaddr) 
    if res.is_reached():
        return True
    else:
        return False

if __name__ == '__main__':
    ipaddr = "対象のIPアドレス"
    ngcount = 0

    while True:
        if send_ping(ipaddr):
            ngcount = 0
            print(datetime.datetime.now(),"ping OK")
        else:
            ngcount += 1
            print(datetime.datetime.now(),"ping NG",ngcount)
            if ngcount >= 5:
                 line("ping失敗。送信先({})機器を確認してください。".format(ipaddr))
                 break

        time.sleep(5)
```

# つまづいたところ
pingsライブラリをインポートしてpingを送信しますが、プログラム実行はsudoコマンドでスーパーユーザ権限を持って実行しないとpingが通りませんでした。Linuxチョットワカラナイ

# 感想
簡単なpingのプログラムで死活監視をやってみました。死活監視はいろいろな方法があるのでやってみたいですね。
CronWorkflowの動作検証2

## はじめに
CronWorkflowのスケジュール実行で前回Workflowが次の実行予定時刻までに完了しなかった場合の動作に関して検証する。
検証では、複数のマニフェストの設定について検証する。

なお、Cronworkflowはspec.workflowSpecでWorkflowTemplateを利用する事を前提とする。

## 検証方法
以下4つの設定で動作検証する。

|項目|設定方法|
|--|--|
|設定①|CronworkflowのconcurrencyPolicyを"Forbid"で指定|
|設定②|CronworkflowのconcurrencyPolicyを"Forbid"で指定し、StartingDeadLineSecondsの秒数を指定|
|設定③|CronworkflowのconcurrencyPolicyを"Allow"で指定|
|設定④|CronworkflowのconcurrencyPolicyを"Allow"で指定する。また、参照するWorkflowTemplateでsynchronizationのmutexを設定する事で同一WorkflowTemlateを同時実行する事を防ぐ|

CronWorkflowは、1分周期でスケジュール実行する設定とする。参照するWorkflowTemplateは1分間sleepするようプログラムする。このように設定する事で前回Workflowが次の実行予定時刻まで動作し続ける状況を作る。

## 検証結果
設定ごとの動作検証結果を下表に示す。

|項目|動作検証結果|
|--|--|
|設定①|今回実行予定のworkflowをスキップする|
|設定②|前回workflowが完了した後に、今回実行予定のworkflowを数秒遅れで開始する|
|設定③|前回workflowの完了を待たずに、今回workflowを開始する|
|設定④|前回workflowが完了した後に、今回実行予定のworkflowを数秒遅れで開始する|

設定②と設定④の結果は同一であるが、startingDeadLineSecondsは指定する秒数内の遅延のみ許容する。このため、前回workflowの完了タイミングによらず必ずスケジュールしていたworkflowを実行したい場合は設定④を採用する必要がある。

## 参照資料
[Argo Workflows Webサイト](https://argoproj.github.io/argo-workflows/)
CronWorkflowの動作検証１

## はじめに
workflow-controllerのダウンとCronWorkflowのスケジュール実行が重なった場合にスケジューリングされているworkflowが実行されるか動作検証する。

## 検証方法
CronWorkflowのスケジュール実行直前にworkflow-controllerのpodをdeleteした場合に、スケジューリングされているworkflowが実行されるかを検証する。

CronWorkflowは、1分周期でスケジュール実行する設定とする。また、CronWorkflowのstartingDeadlineSecondsの設定ごとの動作を確認するため、以下3パターンの設定で動作検証する。

|項目|startingDeadlineSecondsの設定|
|--|--|
|設定①|設定無し|
|設定②|5秒を指定|
|設定③|30秒を指定|

スケジュール実行の10秒前にworkflow-controllerを削除するために、X分00秒に'''$ sleep 50 && kubectl delete pod workflow-controller-xxxxx'''を実行し、X+1分00秒にworkflowが実行されるか確認する。

## 検証結果
検証結果を下表に示す。startingDeadlineSecondsを設定しstartingDeadlineSecondsの設定時間内にworkflow-controllerが復旧動作する場合、スケジューリングされていたworkflowが遅れて実行される事を確認した。

|項目|検証結果|
|--|--|
|設定①|workflowは実行されない|
|設定②|workflowは実行されない|
|設定③|workflowは15秒程度遅れて実行される|

## 参考文献
[Argo Workflows Webサイト](https://argoproj.github.io/argo-workflows/)
Azureのネットワーク切り替え時において切り戻しを想定して考えておくこと（リソース編）


**概要**

　先日、VPN→ExpressRouteへの切り替え作業を実施した。
　切り替えでは、リソースの削除や追加を行うことになるが、この時に切り戻しを想定したときに
　重要となるリソースを2つあげます。

　なお、切り替え時には下記2つ以外にも元の設定内容についてはしっかりと控えておくことが大切です。
　また、ゲートウェイの作成では時間がかかるので焦らずに作業を進めましょう。

<hr>

**重要リソース**

　**ローカルネットワークゲートウェイ（LNG）**
　　作業後の疎通確認やNW速度が安定していることを確認できるまで削除しないこと。

　**接続**
　　作業前にLNGと結びついていた接続は削除（無効）にするが、仮に切り戻しをする際にはLNGに確実に結びつけるため、しっかりと設定内容を控えておくこと。
【備忘録】BingChatを使ってみた感想（macOSで使用するための導入方法）

# はじめに
- 本記事は、備忘録としてまとめたものになります。
- 他の方の参考になる可能性も踏まえて、一般公開も行なっております。
- また記載内容はすべて、正しい内容が記載されているとは限りません。
- 誤った内容を見つけた場合は、ご指摘をお願いいたします。

# この記事は誰向けの記事か？
- BingChatを使ってみたい人
- macOSでBingChatを使ってみたい人（Edgeブラウザをインストールする必要がある）

# 背景
- ChatGPTを頻繁に使うようになったが、2021年9月までの情報でしか、学習されていないため、最新の情報に対する回答ができなかった。
- この問題に対して、何かしら対応ができないかと調査をしたところ、BingChatを使用すれば、この問題を解決できるのではないかと考え、BingChatを使うことにした。
- 使ってみた感想を、備忘録として記録に残しました。

# はじめに
ChatGPTに直接、学習している情報について聞きました。やはり2021年9月までの学習しかしていないようで、最新の情報を提供することは困難のようです。
![スクリーンショット 2023-04-05 17.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/c85fb501-3371-dae5-ea8e-9c8c7a0a14ee.png)

試しに、今日の関西の天気を聞いてみましたが、他のサービスで確認する旨を、勧められてしまいました....
![スクリーンショット 2023-04-05 17.42.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/ef16ca94-2f63-c745-cd43-bc965119c572.png)

# BingChatを使用するための準備
1. 実際にチャットを開始しようとしたが、現在（2023/4/5時点）ではEdgeブラウザでのみ、使用することができない様子。
https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx
![スクリーンショット 2023-04-05 16.59.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/ad11584a-ae3a-f6ba-c0ab-54de731f9278.png)
2. アクセスすると、Edgeをダウンロードし、インストールする旨のページにつながった。
![スクリーンショット 2023-04-05 16.59.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/d6675605-b12e-df1b-f015-f0a125bd0d74.png)
3. 対応するOSに応じたファイルをダウンロードしましょう。（私自身、macOSやiOSでEdgeをインストールできることを、この時、初めて知りました）
![スクリーンショット 2023-04-05 16.59.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/d00fb6c2-b31b-1232-f491-fe1019b1b6d8.png)
4. そのままEdgeをインストールして、Edge上でBingChatを開くだけ。
https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx
![スクリーンショット 2023-04-05 16.59.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/5984385c-32ef-2396-517b-afb30c15852c.png)

# BingChatを使用した結果
1. 試しに最新の天気予報を聞いてみたところ、正しい情報を提供してくれました。
![スクリーンショット 2023-04-05 17.07.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/f8b3b528-667f-7a69-d1b2-653efa972068.png)
アクセスすると、アクセス先で本日の天気を把握することができました。
![スクリーンショット 2023-04-05 17.08.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/5641ceed-c3c3-f651-668e-405810c1a4f6.png)
質問の内容によっては、回答が異なり、一目でわかる回答も得られました。
![スクリーンショット 2023-04-05 17.59.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/ba14c0b2-6ba1-fe12-e672-20caf0f3b404.png)

# 感想
ChatGPTとBingChat、それぞれメリット・デメリットあると思うので、ユーザーの状況（ケースバイケース）で利用していくことが良いのかな、ということを感じました。

私の場合は、プログラムソースコードやちょっとした知識を質問し、回答してもらう、ということが多いので、当面はChatGPTを活用していくことが多いと思います。

# 各種評価
- ChatGPT
https://chat.openai.com
知識的なことを知りたい場合や必要な情報をリスト形式や表形式で手に入れたい場合、プログラミングする際に必要なコードを出力してもらったり、コードレビューしてもらったりといったことは、ChatGPTですることがおすすめだと感じた。理由としては、レスポンスがBingChatよりも早いと感じたためです。

- BingChat
https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx
最新の情報を単に知りたいなどは、BingChatを使うことがおすすめなのかな、と感じました。しかし、これでは、単にググった方が早いような気がしています。これからのアップデートに期待です。
turborepoでRemixとDocusaurusを管理する場合に発生したエラー

Remixプロジェクトが、`apps/*`に存在する状態で、Docusaurusプロジェクトを`apps/*`に作成しました。

その際に、`npm run start`を実行したところ、`Compiles with problems:`というエラーが発生しました。

```bash
Compiled with problems:
×
ERROR
pathname.match is not a function
TypeError: pathname.match is not a function
```

次に、`npm run build`を実行したところ、次のように表示されました。

```bash
[ERROR] Docusaurus server-side rendering could not render static page with path /404.html.
...
TypeError: pathname.match is not a function
    at Array.some (<anonymous>)
    at Array.map (<anonymous>)
...
[ERROR] Unable to build website for locale en.
[ERROR] Error: Failed to compile with errors.
...
```

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/39685b22-e5e4-47bc-049d-2b948667d3df.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/b76fd7ac-3109-1029-f879-48b0e46fb47b.png)

この問題は、次の手順を実行することで解決しました。

1. すべてのワークスペースの`node_modules`を削除する。
2. ルートディレクトリの`package-lock.json`を削除する
3. ルートディレクトリにて、`npm install`を実行する。

結果、`npm run start`と`npm run build`の実行に成功しました。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/7446f3ec-cac4-b69b-3aa7-93687ffb7fb3.png)

https://github.com/facebook/docusaurus/issues/7532#issuecomment-1142551983
Teamsのチャットでファイル共有ができないときに確認したいこと

**この記事を書いた背景**

会社でTeamsを使っていますが、チーム（チャネル）ではファイル共有ができるが、チャットではファイル共有ができませんでした。何でもないときに、この理由について気になったので、軽く理由を調べました。

<hr>

**結論**

　Teamsのファイル共有において、チーム（チャネル）では「SharePoint」が、チャットでは「OneDrive」が使用されていますが、私の会社ではOneDriveの使用が制限されていました。

この制限の理由としては、諸説ありますが、セキュリティ対策が有力でした。
というのもOneDriveでは1TBもの容量が使えるそうで、そんなに使えたら個人間でなんでも送りあえてしまうからとかなんとか。

<hr>

**そもそもSharePointとOneDriveってなにか**

・SharePointとOneDriveは、両方ともMicrosoftが提供するクラウドストレージサービスであり、ファイルの共有やMicrosoft Officeアプリケーションとの統合を可能にします。ただし、それぞれのサービスには異なる特徴や使い方があります。

**SharePoint**

・企業や組織内での文書管理やコラボレーションを目的としたサービス。
・SharePointは、ドキュメントやリスト、カレンダーなどの情報を管理でき、組織内の情報共有やコラボレーションに向いている。

**OneDrive**

・個人がファイルを保存し、必要に応じて共有するためのサービス。
・個人のファイルをクラウド上に保存し、どこからでもアクセスできるようにすることができ、個人的なファイルの共有や保存に向いている。

以上のように、SharePointは企業や組織内での情報共有やコラボレーションに向いており、OneDriveは個人的なファイルの共有や保存に向いています。しかし、どちらのサービスも柔軟に使い分けることができ、目的に応じて利用することができます。

<hr>

**OneDriveの設定はどこからするのか**

OneDriveは、以下のSharePoint管理センターから設定していきます。
https://go.microsoft.com/fwlink/?linkid=2185222
【VSCode】MarkdownをPDFに変換する


## `.md`を`.pdf`に変換する方法
Markdown PDFという拡張機能を使用することでMarkdownをPDFに変換できます。

https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf

## 基本的な使用方法
Markdown PDFをインストールします。
`.md`ファイルを開き、右クリックします。
![E1930970-712A-4E0F-92AD-6843DB29C2B4のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/7e4d2aac-3349-cecb-9804-d5c9ba647f4b.png)

`Markdown PDF:Export(pdf)`を選択します。

すると`.pdf`が作成されます。
![スクリーンショット 2022-07-31 午前6.23.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/2d42158e-2ad2-223a-e7c8-863112e656ac.png)

`pdf`以外にも`html`, `png`, `jpeg`に変換できます。

## 主な設定
* `markdown-pdf.convertOnSave`  
ファイル保存時にpdfなどを出力します。

* `markdown-pdf.type`  
ファイル保存時に出力されるファイルを選択できます。
```setting.json
    "markdown-pdf.type": [
      "pdf",
      "html"
    ],
```
上記のように設定すると`pdf`と`html`が出力されます。

* `markdown-pdf.styles`  
cssファイルのパスを指定することでstyleを変更できます。
htmlファイルを出力する際にはオンラインCSSを指定しないと適用されません。
ただしオンラインCSSを指定するとPDFで問題が発生するようです。

* `markdown-pdf.outputDirectory`  
ファイルの出力先を指定できます。

* `markdown-pdf.displayHeaderFooter`
PDFのヘッダーとフッターの表示・非表示を切り替えます。
Git git commitコマンド実行後エラーが出る

# 概要

- `$ git commit`コマンド実行後にエラーが出て困ったので自分の場合の解決方法をまとめる。

# エラー

- `$ git commit`を実行してvimが開き、vim内で下記のエラーが出る。

    ```
    E349: No identifier under cursor
    ```

- :wqで保存してターミナルに戻ると下記のエラーが出ている。

    ```
    hint: Waiting for your editor to close the file... error: There was a problem with the editor 'vi'.
    Please supply the message using either -m or -F option.
    ```

# 解決方法

- 下記コマンドを実行してコミットメッセージ記入時のエディタを明示的に指定した。

    ```
    git config --global core.editor "vim"
    ```
【Git】"fatal: detected dubious ownership in repository at..."というエラーが出た場合に考えられる原因と解決策

# 概要
* `git branch`を実行したら、`fatal: detected dubious ownership in repository at...`というエラーメッセージが出てきました。本記事ではその原因と解決方法を記します。

# エラーメッセージと意味
* EC2インスタンスで`git branch`を実行したら、、

```terminal
$ git branch
fatal: detected dubious ownership in repository at '/var/www/html/sample_homepage'
To add an exception for this directory, call:

	git config --global --add safe.directory /var/www/html/sample_homepage
```

* 上記のエラーメッセージが返ってきました。初めてみるメッセージでした。
* 調べてみると、gitが指定されたリポジトリのディレクトリ所有者に疑念を抱いていることを示しているとのこと。

## 原因
* Gitが一般的に使用されるデフォルトのユーザー名とグループ名（一般的には`"git"`）と、実際にはファイルにアクセスするために使用されるユーザー名とグループ名が異なる場合に発生することがあるらしい。
* 例えば、EC2インスタンス上で実行されるApacheウェブサーバーの場合、`"apache"`ユーザーと`"apache"`グループがファイルにアクセスするために使用されます。`"git"`ユーザーと`"git"`グループによって所有されていることを期待しているのに、実際には異なるユーザーとグループによって所有されているため、Gitが警告を出すということです。

## 解決策
* エラーメッセージで提案されているように、次のコマンドを実行して、Gitに安全なディレクトリとして指定してあげると解決します。

```terminal
$ git config --global --add safe.directory /var/www/html/sample_homepage
```

* これにより、Gitはこのディレクトリに対して警告を出さなくなります。
    * 自分の場合はこれで`git branch`もできるようになりました。
    * 必要に応じて、ファイルにアクセスするために使用されるユーザーとグループに合わせて、ディレクトリの所有者を変更することもできます。
* ディレクトリの所有者が間違っている場合にも同じメッセージが出ます。具体的には以下のコマンドを使います。
    * usernameとgroupnameは、実際にディレクトリを使用するユーザーとグループに置き換えます。

```terminal
$ sudo chown -R username:groupname /var/www/html/sample_homepage
```

* 今回のエラー対応の参考記事
    * [【Git】fatal: detected dubious ownership in repository 解消法](https://qiita.com/P-man_Brown/items/31fb824be461d20be0b8)
    * [[git]操作時にdetected dubious ownership in repositoryが発生するようになった](https://qiita.com/nekotouma0114/items/5206607584ccef5fb6b5)
サービスクラスの作成設定（Laravel）

## 初めに
Laravelのサービスクラスの設定をしましたので
備忘録、テンプレートとして残します。

## 環境
| 開発環境   |バージョン    |
|-----------|------------|
| __Laravel__ | 10.1.5 |
| __PHP__ | 8.2.3 |

## 実装前
今回は、HomeController.phpに着目していきます。
まずは、Serviceを紐付ける前のソースです。

```php:HomeController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class HomeController extends Controller
{
    // コンストラクタ
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index(Request $request)
    {
        Log::debug(__FUNCTION__);

        return view('home');
    }
}
```


## 実装後

app配下にServicesディレクトリを作成します。

実装します。
実装後のソースコードになります。
```php:HomeController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Services\HomeService;

class HomeController extends Controller
{
    protected $service;

    // コンストラクタ
    public function __construct(HomeService $service)
    {
        $this->middleware('auth');

        // 初期設定
        $this->service = $service;
    }

    public function index(Request $request)
    {
        Log::debug(__FUNCTION__);

        $this->service->test();

        return view('home');
    }
}
```

HomeService.phpファイルを作成します。
実装します。
```php:HomeService.php
namespace App\Services;

use Illuminate\Support\Facades\Log;
 
/**
 * HOMEサービスクラス
 *
 */
class HomeService
{
    // コンストラクタ
    public function __construct()
    {
        Log::debug(get_class($this));
    }

    public function test()
    {
        Log::debug(__FUNCTION__);
    }
}
```

気をつけるポイントとして、パスに注意してください。
例：App\Service　ではなく　App\Services
   "s"をつけること



## 最後に
最後まで閲覧いただきありがとうございました。
ご意見、ご指摘ありましたら、コメントお願いいたします。
nvmのインストール方法【Node Version Manager】

# nvmのインストール方法
1.Node Version Manager（nvm）をダウンロードする。
  - https://github.com/coreybutler/nvm-windows/releases
    ![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/e54ff160-1148-0f33-84ce-3d91a937530b.png)
2.`nvm-setup.exe` を起動する。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/10333520-758f-f790-6640-787478746c65.png)
3.`I accept the agreement` を選択し、 `Next` を押下する。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/dde7e18a-da31-6578-82a2-088ef5eeaf53.png)
4.`Next` を押下する。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/c337a0b3-b005-134c-e132-67c3de8549b8.png)
5.`Next` を押下する。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/5a61ca97-95bf-d27a-8d36-b82f50614072.png)
6.`Install` を押下する。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/717e4ca8-2cdf-0ea7-23dd-8001aee9b947.png)
7.`Finish` を押下する。

# node.jsインストール
1.`nvm version` コマンドでバージョンを確認する。
```
>nvm version
1.1.10
```
2.`nvm list available` コマンドでインストール可能なnode.jsバージョンを確認する。
```
>nvm list available

|   CURRENT    |     LTS      |  OLD STABLE  | OLD UNSTABLE |
|--------------|--------------|--------------|--------------|
|    19.8.1    |   18.15.0    |   0.12.18    |   0.11.16    |
|    19.8.0    |   18.14.2    |   0.12.17    |   0.11.15    |
|    19.7.0    |   18.14.1    |   0.12.16    |   0.11.14    |
|    19.6.1    |   18.14.0    |   0.12.15    |   0.11.13    |
|    19.6.0    |   18.13.0    |   0.12.14    |   0.11.12    |
|    19.5.0    |   18.12.1    |   0.12.13    |   0.11.11    |
|    19.4.0    |   18.12.0    |   0.12.12    |   0.11.10    |
|    19.3.0    |   16.20.0    |   0.12.11    |    0.11.9    |
|    19.2.0    |   16.19.1    |   0.12.10    |    0.11.8    |
|    19.1.0    |   16.19.0    |    0.12.9    |    0.11.7    |
|    19.0.1    |   16.18.1    |    0.12.8    |    0.11.6    |
|    19.0.0    |   16.18.0    |    0.12.7    |    0.11.5    |
|   18.11.0    |   16.17.1    |    0.12.6    |    0.11.4    |
|   18.10.0    |   16.17.0    |    0.12.5    |    0.11.3    |
|    18.9.1    |   16.16.0    |    0.12.4    |    0.11.2    |
|    18.9.0    |   16.15.1    |    0.12.3    |    0.11.1    |
|    18.8.0    |   16.15.0    |    0.12.2    |    0.11.0    |
|    18.7.0    |   16.14.2    |    0.12.1    |    0.9.12    |
|    18.6.0    |   16.14.1    |    0.12.0    |    0.9.11    |
|    18.5.0    |   16.14.0    |   0.10.48    |    0.9.10    |

This is a partial list. For a complete list, visit https://nodejs.org/en/download/releases
```

3.`nvm install 【バージョン】` コマンドでnode.jsをインストールする。
```
>nvm install 18.15.0
Downloading node.js version 18.15.0 (64-bit)...
Extracting node and npm...
Complete
npm v9.5.0 installed successfully.


Installation complete. If you want to use this version, type

nvm use 18.15.0
```

4.`nvm list` コマンドでインストールしたnode.jsバージョンを確認する。
```
>nvm list

    18.15.0
```

5.`nvm use 【バージョン】` で使用するnode.jsバージョンを選択する。
```
>nvm use 18.15.0
Now using node v18.15.0 (64-bit)
```

6.node.jsのバージョンを確認する。
```
>node -v
v18.15.0

>npm -v
9.5.0
```
ショートカットアプリでYahoo!路線情報の事故遅延情報を取得する

# 要約
通勤で利用している全路線の運行状況を朝一番お手軽に確認したい。しかし、既存のアプリやそのウィジェットによる確認は少々手間である。そこで、事故や遅延が発生している路線の情報のみを起床と同時に読み上げられるよう、ショートカットアプリのアクションを作成した。


# イントロ
2023年4月、筆者は晴れて新社会人となった。
これまでキャンパス付近に家を借りていたため徒歩のみでの通学をしていた。
しかし、入社後は指定の社宅に入居し通勤しなければいけなくなった。
社宅は会社の近くにあるわけではなく、約30分ほど電車に乗らなければいけない。

# 路線の運行情報の確認
通勤が鉄道に依存する以上、毎朝確認しなければいけないことが使用する路線の運行情報である。
路線に事故や遅延が発生した場合、路線を変更したり上司からの対応を仰いだりする必要がある。
~~そこまでして通勤しなければいけないのかは置いといて(研修後で社畜精神を塗り込まれたわけではないと断ってはおく)。~~


# 王道ツール
路線情報として有名なのは **Yahoo!路線情報の"運行情報"** である。

https://transit.yahoo.co.jp/diainfo

このツールはYahoo!が提供元であることはもちろん、機能の充実したアプリが魅力の一つである。
中でもウィジェット機能が優秀である。

https://otona-life.com/2022/07/31/129717/ 

ウィジェットは、ホーム画面やロック画面に設置できる可視性の優れた縮小版のアプリのようなものである。わざわざホームページやアプリを開かなくてもウィジェット機能を使用することで路線の確認はできる。


# 面倒くさがりな性分
しかし、利用している複数の路線の運行情報を確認することはかなり面倒くさく感じる。
特に、できるだけエネルギーを使いたくない出勤前の朝方のだったらなおさらである。
わざわざアプリを開いてぽちぽち閲覧するのも億劫であり、目を使って情報をインプットしたくない。


# できるよ、ショートカットアプリならね。
そんな悩みも**ショートカットアプリ**なら簡単に解決してくれる。
見るのが面倒であれば、読み上げさせてあげればいい。
ということで、起床後のアラーム停止を起点として、路線情報の読み上げを行なってもらうことにした。


# 路線の事故遅延情報アプリ
路線情報のリソースにはやはりYahoo!路線情報を用いた。
Yahoo!路線情報からの情報取得および情報の抽出は以下の記事を参考にした。
平常運転の場合と事故遅延の場合で、記載されている情報が異なる。

https://qiita.com/hirohiroto522/items/6ff29be1344be805ecb0

また、情報の抽出は以下の記事を参考にした。
不慣れではあったが、正規表現を用いたスクレイピングを行えるようになった。


https://qiita.com/sentencebird/items/e537ad94bdd0f697f432

https://arc-tech.hatenablog.com/entry/2021/01/20/105620


# アプリ構成
ショートカットアクションは以下の構成で作成した。

* リストの設定
    * Yahoo!路線情報から使用している路線のURLをコピペする
* 事由変数の設定
    * デフォルトを0とする
    * 事故遅延の事由があれば1を加える
 **↓以下の項目をリストのすべての項目で繰り返す↓** 
* URLリストからURL先のHTMLの情報を取得する
* HTMLの情報から事故や遅延があるかチェックする
* ifで分岐
    * 事故や遅延がある場合
        * 路線名と事故遅延状況情報の抽出
        * 即座に路線名と事故遅延状況を読み上げる
        * 事由変数に1を加える
 **↑繰り返し終わり↑** 
* ifで分岐
    * 事由変数が0だった場合
        * 「現在全路線は平常通り運転しています」と読み上げる
    * 事由変数が1以上だった場合
        * 「その他の路線は平常通り運転しています」と読み上げる


# ショートカットの利用について
ショートカットを取得したら、リストに利用する路線情報のURLを貼り付ける。
その後、オートメーションから起床アラーム停止後のアクションとしてこのショートカットを起動するように設定する。


# ショートカットの配布
以下に共有用のリンクを貼っておきます。
ダウンロードにはiPhoneの設定 > ショートカット > 信頼されていないショートカットを許可をオンにする必要があるので各自設定の変更が必要です。

https://www.icloud.com/shortcuts/e913446a60cf4698a9fa511be1eed5f0
Athenバージョンアップ

"IGNORE NULLS"を使用してNULLを無視することができなくなりました。BOOL_OR関数を使用する際には、BOOL_OR(col1, col2)のように省略せずに使用する必要があります。
sql
Copy code
-- Before
SELECT COUNT(*) FROM table WHERE BOOL_OR(col1, col2) IGNORE NULLS;
-- After
SELECT COUNT(*) FROM table WHERE BOOL_OR(col1, col2);
CONCAT関数には、二つ以上の引数が必要になりました。以前は、一つの引数でも使用することができましたが、今後は使用できません。
sql
Copy code
-- Before
SELECT CONCAT(col1) FROM table;
-- After
SELECT CONCAT(col1, '') FROM table;
GROUP BY句で、ネストされた列名を使用する場合には、ダブルクォーテーションで囲む必要があります。
sql
Copy code
-- Before
SELECT "user"."name" FROM dataset GROUP BY user.name;
-- After
SELECT "user"."name" FROM dataset GROUP BY "user"."name";
MINUTE()関数には、YEAR TO MONTHのインターバルを渡すことができなくなりました。代わりに、EXTRACT関数を使用する必要があります。
sql
Copy code
-- Before
SELECT minute(interval '1 year 2 months');
-- After
SELECT extract(minute from interval '1 year 2 months');
ORDER BY句で使用する式は、SELECTリストに含める必要があります。以前は、SELECTリストに含まれていなくても使用できましたが、今後は使用できません。
sql
Copy code
-- Before
SELECT DISTINCT col1 FROM table ORDER BY col2;
-- After
SELECT DISTINCT col1, col2 FROM table ORDER BY col2;
SYSTEM_TIMEとSYSTEM_VERSION句が非推奨となり、代わりに、FOR TIMESTAMP AS OF句を使用する必要があります。
sql
Copy code
-- Before
SELECT * FROM TABLE FOR SYSTEM_TIME AS OF '2022-03-04 10:00:00';
-- After
SELECT * FROM TABLE FOR TIMESTAMP AS OF '2022-03-04 10:00:00';
DECIMAL型への変換がサポートされなくなりました。例えば、VARCHAR型からDECIMAL型への変換はできません。
sql
Copy code
-- Before
ALTER TABLE table ALTER COLUMN col1 TYPE varchar;
-- After
ALTER TABLE table ALTER COLUMN col1 TYPE decimal;
文字列からTIMESTAMP型に変換する際に、日付と時刻の間にスペースを入れる必要があります。以前は、スペースがなくても使用できましたが、今後は使用できません。
sql
Copy code
-- Before
SELECT CAST('2021-06-06-23:38:46' AS timestamp) AS this_time;
-- After
SELECT CAST('2021-06-06 23:38:46' AS timestamp) AS this_time;
Github Actions Dockerで環境構築しているコードをCIチェックするときにエラーが出た

# 概要

- Dockerでローカル開発環境を構築しているコードをGithub上でPR作成するときにCIチェックでテストが走るようにしたい。
- `$ docker compose up`後にcomposer installを実行したところエラーが出たので自身の環境の解決方法をまとめる。

# 前提

- 下記のようなワークフローのyamlファイルを定義した。（環境構築は`$ make init`コマンドを実行するだけで完了するように下準備はしてある。）

    ```phpunit.yaml
    name: 'do PHPUnit'
    
    on:
      push: 
        branches:
          - 'feature/*'
          - 'hotfix/*'
          - 'release/*'
      pull_request:
        types: [opened, reopened]
    
    jobs:
      do_phpunit:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - name: init
            run: make init
          - name: check echo
            run: echo 'init end'
    ```

# 問題

- 下記エラーが出て止まった。

    ```
    docker-compose exec api composer install
    the input device is not a TTY
    make: *** [Makefile:27: composer_install_for_api] Error 1
    Error: Process completed with exit code 2.
    ```

# 原因

- TTYが無いためエラーになっている模様、、！
- Makefile内のcomposer installを実行している部分を下記のように修正した。

    ```Makefile
    .PHONY: composer_install_for_api
    composer_install_for_api:
    	docker-compose exec -T api composer install
    ```

- 上記の状態でcommitしてpushしたところ本エラーは出なくなった。

# その後の話し

- composer installコマンドに限らず、Actionsで実行するコンテナ系のコマンドはすべて-Tをつけないとエラーになるっぽいです。
[AWS Glue]開発エンドポイントをCLIで削除する

# はじめに

開発エンドポイントがマネジメントコンソールから削除できない場合があることと、CLIで削除する手順を記載しています。

## 発端

マネジメントコンソールからAWS Glueの開発エンドポイントを削除しようとしましたが、
メニューから「開発エンドポイント」を見つけることができず、CLIで削除しました。
シドニーリージョンでは「Legacy pages」に「開発エンドポイント」メニューがあり、ここから生成や削除が可能でした。

![](https://raw.githubusercontent.com/kenryo012/qiita-content/main/images/Glue_Delete_Dev_Endpoint/sydney.png)

一方、東京リージョンでは「開発エンドポイント」メニューが見当たりませんでした。
シドニーリージョンの「開発エンドポイント」画面のURLを東京リージョン用に変換しても、別のメニューに遷移しました。

![](https://raw.githubusercontent.com/kenryo012/qiita-content/main/images/Glue_Delete_Dev_Endpoint/tokyo.png)

開発エンドポイントは高いらしいのでなるべく早く削除したいです。

https://qiita.com/yomon8/items/8642d68a52454508aa60

## どうしたか

仕方がないのでAWS CLIで削除しました。

`aws glue delete-dev-endpoint --endpoint-name "<エンドポイント名>"`で削除することができます。
また、`aws glue get-dev-endpoint --endpoint-name "<エンドポイント名>"`でエンドポイントに関する情報を取得できます。
以下が実行例です。

![](https://raw.githubusercontent.com/kenryo012/qiita-content/main/images/Glue_Delete_Dev_Endpoint/tokyogetcli.png)

![](https://raw.githubusercontent.com/kenryo012/qiita-content/main/images/Glue_Delete_Dev_Endpoint/tokyodeletecli.png)

## 参考

- https://awscli.amazonaws.com/v2/documentation/api/latest/reference/glue/get-dev-endpoint.html
- https://awscli.amazonaws.com/v2/documentation/api/latest/reference/glue/delete-dev-endpoint.html
Phpstormが重くなった時のTips

Phpstormはメソッドジャンプや全検索をサクサク使える便利なIDEですが、反面、メモリを食べ過ぎて動作が遅くなってしまうときがあります。そんな時に試してほしい設定があります。

# 目次
- [最大ヒープサイズを変更する](#最大ヒープサイズを変更する)
- [ガベージコレクションをする](#ガベージコレクションをする)
- [ディレクトリに除外フラグを立てる](#ディレクトリに除外フラグを立てる)

## 最大ヒープサイズを変更する
ヘルプ > メモリ設定を変更　から最大ヒープサイズを変更することができます。初期値は750MiBとかだったと思いますが、これを変更することで使用できるメモリが増え、動作が軽くなることがあります。

## ガベージコレクションをする
画面右下のステータスバーを右クリックして、「メモリインジケータ」にチェックを入れると、メモリ使用量表示エリアが現れます。このメモリ使用量表示エリアをクリックすることでガベージコレクションができます。
なお、このガベージコレクションはアプリケーション全体に対するものではないので、効果を実感できるほどのものではないですが、気持ち軽くなる感じです。

## ディレクトリに除外フラグを立てる
Phpstormでは、全検索のために全ファイルに対してインデックスをはろうとします。もし、プロジェクトディレクトリ配下に全検索が必要なディレクトリ（Vender）などがある場合、除外フラグを立てることでインデックスを作成する時間が無くなり、Phpstormが軽くなります。
【学習記録】JavaScript

## コールバック関数について
#### コールバック関数を用いることで、繰り返し実行される関数をまとめて記述できる
##### -コールバック関数を用いた表現-
```
//⑤関数unfollowが実行される
function unfollow() {
    console.log('フォローを外しました');
}

function cancelTweet() {
    console.log('ツイートをキャンセルしました');
}

//②(fn)が関数unfollowを受け取り、関数confirmedが実行される
function confirmed(fn) {
    //③ブラウザにYorNウィンドウが表示され、Yesを選択するとifがTrueになる
    if (window.confirm("実行しますか？")) {
        //④if = Trueのとき、(fn)で受け取った関数unfollowを呼び出す
        fn();
    }
}
//①引数unfollowを入れて関数confirmedを呼び出す
confirmed(unfollow);
```
##### -コールバック関数を用いない表現-
```
function unfollow() {
    if (window.confirm("実行しますか？")) {
        console.log('フォローを外しました');
    }
}

function cancelTweet() {
    if (window.confirm("実行しますか？")) {
        console.log('ツイートをキャンセルしました');
    }
}
unfollow();
```
##### この様に関数を実行する際に都度if文を記述する必要があり、保守性に欠けてしまう
競プロのテクニック 商列挙

# 0 はじめに
## 0-1 あいさつ
こんにちは。

## 0-2 記事の説明
競プロで稀に用いられるテクニック「商列挙」について説明します。
商列挙の説明や証明、実装を書きました。

## 0-3 動機
ABC296-Dを解いてる時に「あーなんか商列挙みたいなのあったな～」って思って思い出したので書きます。

# 1 本題

## 1-1 商列挙とは
商列挙とは、名前だけでは中々分かりづらい内容ですが、次のようなテクニックを指します。
> ある自然数$N$について、$\lfloor \frac{N}{i} \rfloor(1 \leq i \leq N)$の値を$O(\sqrt N)$で全て列挙する。

商というのは$\lfloor \frac{N}{i} \rfloor$の部分を指しているのですね。


列挙の計算量と同じく、商の値の種類も$O(\sqrt N)$種類です。
確かに言われてみればそんな気はしますが何故平方根になるのでしょうか。

## 1-2 平方根になる証明

証明します。

まず、「自然数$N$の商の値の種類」は、次のように言い換えることができる。
(関数$f(x)=\lfloor \frac{N}{x} \rfloor(1 \leq x \leq N)$は広義単調減少である為)

> $\lfloor \frac{N}{i} \rfloor \neq \lfloor \frac{N}{i+1} \rfloor$(...①)なる$i(1 \leq i \leq N-1)$の数。

よってこれを求めればよいことになる。

$(1) \frac{N}{i}-\frac{N}{i+1} \geq 1 $の場合
整数部分の差は必ず1以上であるから、①は絶対に成り立つ。
これを満たす$i$の範囲は、
```math
\begin{align*}
\frac{N}{i}-\frac{N}{i+1} \geq 1 &\Leftrightarrow \frac{N}{i(i+1)} \geq 1\\
&\Leftrightarrow N \geq i(i+1)
\end{align*}
```
即ち、凡そ$i \leq \sqrt N$である。…②
従って、この範囲にある商は約$\sqrt N$種類である。

$(2) \frac{N}{i}-\frac{N}{i+1} ＜ 1 $の場合
②により、$\frac{N}{i}-\frac{N}{i+1} ＜ 1$を満たす$i$の範囲は$\sqrt{N} \leq i \leq N$であるから、$\lfloor \frac{N}{i} \rfloor$の値は$1$以上$\sqrt{N}$以下を取る。
従って、この範囲にある商も約$\sqrt N$種類である。

以上より、$\lfloor \frac{N}{i} \rfloor(1 \leq i \leq N)$の種類数は$O(\sqrt N)$個である。

## 1-3 実装

### 1-3-1 一つ目の実装

上の事実を使います。
確実に連続して商が存在する区間は凡そ$[1,\sqrt N]$ですから、残りの部分を調べればよいです。
$i(1 \leq i \leq \sqrt{N}+10)$(10は保険かけてます)くらいについて、$\lfloor \frac{N}{i} \rfloor$を列挙し、その中の最小以下の自然数を全て加えておけばよいです。

コードを見た方が早いと思います。 
```py
N=int(input())

L=[]
for i in range(1,int(N**0.5)+10): #証明の(1)の部分
  L.append(N//i)
for i in range(L[-1]-1,0,-1): #(2)
  L.append(i)
#Lは降順になっている
```

+10で保険を掛けているので重複する可能性が高いですが、それは`set`とかで管理しておけば大丈夫だと思います。(計算量重くなりそうですが)
又、商が$i$の区間も同時に列挙したい場合はappendの部分をいい感じに改造すればいいです。

### 1-3-2 while文を用いた実装

```py
N=int(input())

L=[]
l=1
while l<=N:
  L.append(N//l)
  l=N//(N//l)+1 
```
$l$は、商が$\lfloor \frac{N}{i} \rfloor$となる$i$のうち最小のものをとるようになっています。
なのでこんな単純なコードでも商列挙ができます。
これで動く証明はここでは行いませんが考えてみると勉強になるでしょう。
計算量は、勿論商の種類数に等しく$O(\sqrt N)$です。

## 1-4 商列挙を用いる問題

[ABC132-F Small Products](https://atcoder.jp/contests/abc132/tasks/abc132_f) 黄diffらしいです。
[ARC150-B Make Divisible](https://atcoder.jp/contests/arc150/tasks/arc150_b) 良問ですね。
[ABC296-D M<=ab](https://atcoder.jp/contests/abc296/tasks/abc296_d) 私は商列挙しました。

...少ないですね。
商列挙はそこまで使用頻度は高くないです。

# 2 おわりに
お読みいただきありがとうございました。
商列挙の証明が書きたくて書いたこの記事ですが書いていて結構勉強になりました。
よい競プロライフを！
MacでReact Native環境構築










どうもこんにちはたくびー(@takubii)です。

今回はReact nativeの環境構築について紹介したいと思います。
なお、Expoは使わずReact native CLIで構築を行いました。

この記事は2023年3月に書いています。今後のバージョンアップなどで同様の手順では構築できない可能性がありますので、注意してください。

参考

https://reactnative.dev/docs/environment-setup?platform=ios

条件は以下となっております。
- M1 Mac
- IOS、Androidそれぞれエミュレーターで動かす
- React native CLI

### IOS、Android環境共通
```terminal
$ brew install watchman
```
node.jsに関してはバージョン管理できるnvm経由でLTSをインストールします。
```terminal
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
$ nvm install --lts
$ nvm use --lts
```

### IOS
cocoapodsoをインストールするためにRubyをインストールします。
おそらくRubyはデフォルトで入っていると思いますが、バージョンが古いのでrbenvを使用してドキュメントに記載のあるバージョンに変えます。
```terminal
$ brew install rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(rbenv init -)"' >> ~/.zshrc
$ source ~/.zshrc
$ rbenv install 2.7.6
$ rbenv global 2.7.6
$ gem install bundle
```
※rubyの最新バージョンをインストールしたい場合は以下のコマンドでいけます。
```terminal
$ brew install libyaml <- これが必要
$ rbenv install 3.2.1
```
cocoapodsのインストールは公式サイトに従って以下のコマンドで完了です。
```terminal
$ sudo gem install cocoapods
```
X codeも必要なのでインストールしますが、こちらはApp Storeからしかインストールできなかったので、適当なアカウントでApp Storeから落としてきてください。

その後、起動したら[settings...]をクリックし、[Locations]タブの[Command Line Tools]から選択しインストールをします。

IOS固有の環境構築はこれでOKです。

### Android
私の環境ではJDKはすでにインストール済みでしたが、入っていない方は以下のコマンドでJDKをインストールします。
```terminal
$ brew tap homebrew/cask-versions
$ brew install --cask zulu11
```

Androidの開発にはAndroid Studioが必要なので https://developer.android.com/studio/index.html からダウンロードします。

installウィザードにそってインストールしてください。
完了後以下のようにAndroid Studioの設定を行います。
1. [Projects] -> [More Actions] -> [SDK Manager]をクリック[SDK Platforms]タブの右下の[Show Package Details]にチェック
2. [Android 12.0 (S)]内の[Android SDK Platform 31]、[Google APIs ARM 64 v8a System Image]にチェックを入れる
3. [SDK Tools]タブの右下の[Show Package Details]にチェック
4. [Android SDK Build-Tools]内の[31.0.0]にチェックを入れる
5. [Apply]をクリックしインストール

こちらはデバイスの設定です。
1. [Projects] -> [More Actions] -> [Virtual Device Manager]をクリック
2. [Create device]をクリックし、任意のデバイスを選択し[Next]をクリック
3. [S] -> [31]を選択し、[Next]をクリック
4. [Finish]をクリック

Android SDKのパスを通す必要があるので、通します。環境によってはzshをbashに変えてください。
```terminal
$ echo 'export ANDROID_HOME=$HOME/Library/Android/sdk' >>  ~/.zshrc
$ echo 'export PATH=$PATH:$ANDROID_HOME/emulator' >> ~/.zshrc
$ echo 'export PATH=$PATH:$ANDROID_HOME/platform-tools' >> ~/.zshrc
$ source ~/.zshrc
```

これでAndroidの開発環境も完了です。

### プロジェクトを作成し、エミュレーターを起動する
`npx react-native@latest init`コマンドからプロジェクトを作成します。
```terminal
$ npx react-native@latest init ReactNativeTest
$ cd ReactNativeTest
$ npm run start
```
ここまでで、エラーが出なければ問題なく構築完了です。お疲れ様でした。
Androidで起動したい場合は以下で自動的に起動します。
```terminal
$ npm run android
```
IOSで起動したい場合は以下です。
```terminal
$ npm run ios
```

### 最後に
react-native-cliでの構築はX CodeやAndroid Studioが必要だったりで少し複雑でした。
私もとりあえずAndroidだけで構築したときにIOS関連のパッケージがなかったので最初のプロジェクト作成でエラーが出た時はめんどくさって思いました。
それではここまで読んでいただきありがとうございました。また機会があればお会いいたしましょう。
【Swift】ISO8601形式についてまとめた

# はじめに
最近はDateをISO8601形式に変換して使うことが多いです。
後から見返してわかるようにまとめてみました。

# DateからISO8601形式のStringに変換
```swift
let date = Date()

let dateFormatter = ISO8601DateFormatter()
dateFormatter.string(from: date)
```

# ISO8601形式のStringからDateに変換
```swift
let dateString = "2023-04-05T22:32:10Z"

let dateFormatter = ISO8601DateFormatter()
dateFormatter.date(from: dateString)
```

# ミリ秒を含んだISO8601形式
```swift
import Foundation

let dateString = "2023-04-05T22:32:10.123Z"

let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = .withFractionalSeconds
dateFormatter.date(from: dateString)
```

デコード時に`dateDecodingStrategy`を使用してミリ秒を扱うときは以下の記事

https://qiita.com/SNQ-2001/items/8ebfc64419b52779d2b9

# `T`がない
```swift
import Foundation

let dateString = "2023-04-05 22:32:10Z"

let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = .withSpaceBetweenDateAndTime
dateFormatter.date(from: dateString)
```

# `-`がない
```swift
import Foundation

let dateString = "20230405T22:32:10Z"

let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = .withDashSeparatorInDate
dateFormatter.date(from: dateString)
```

# `:`がない
```swift
import Foundation

let dateString = "2023-04-05T223210Z"

let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = .withColonSeparatorInTime
dateFormatter.date(from: dateString)
```

# おわり
オプションは他にもたくさんあります。
今後、使うことがあれば追加していこうと思います。