かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

環境構築 macOS Big Sur : Git の設定と GitHub への SSH 接続

新しいMacに Git の設定やり直したのを書き忘れてたので思い出しながらメモ。

環境

Git のインストール

  1. XcodeXcode Command Line Tools をインストールする
    ターミナルで git --version コマンドを叩くと Command Line Tools をインストールするか聞かれるダイアログが表示されるので Yes を選択すると git が使えるようになる。(楽)
  2. Home brew でインストールする
$ brew install git

Git の設定

global に色々設定する。
設定ファイルは /Users/<user>/.gitconfig に作成される

ユーザー情報
$ git config --global user.name "<NAME>"
$ git config --global user.email "<YOUR E-MAIL>"
デフォルトのエディタをvimにする
$ git config --global core.editor 'vim -c "set fenc=utf-8"'
ファイル名の大文字/小文字を識別する
$ git config --global core.ignorecase false
rebase 時に自動的に --autosquash する
$ git config --global --add rebase.autosquash true

cf. git コミットログを綺麗にしたい。fixupとsquash - かもメモ

git pull の設定

Git v2.27 から git pull のオプションを指定するように Warning が出るようになっているので、fast-forward な時はそのまま marge, fast-forward でない時は マージコミットを作成する今までの挙動 (--ff) をデフォルトに設定する

$ git config --global pull.rebase false

cf. Git 2.27 での git pull 時の warning について - Qiita

カラー設定
$ git config --global color.ui true
$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto
設定の確認
$ git config --global -l

Git コマンドのエイリアスを作成

git checkout とか毎回タイプするの面倒なのでエイリアスを作成する。
エイリアスgit config <option> alias.<alias name> <command> の形で指定する。コマンドにスペースが含まれる場合は ' で囲って文字列で指定できる。

$ git config --global alias.st status
$ git config --global alias.br branch
$ git config --global alias.co checkout
$ git config --global alias.cm commit
$ git config --global alias.gr grep
$ git config --global alias.cp cherry-pick
$ git config --global alias.l log
$ git config --global alias.l1 'log --oneline'
# ログの tree 表示
$ git config --global alias.tree 'log --graph --oneline'
$ git config --global alias.treeall 'log --graph --all --format="%x09%C(cyan bold)%an%Creset%x09%C(yellow)%h%Creset %C(magenta reverse)%d%Creset %s"'
$ git config --global alias.rb rebase
$ git config --global alias.rb2 'rebase -i HEAD~2'
$ git config --global alias.rb3 'rebase -i HEAD~3'
$ git config --global alias.rb4 'rebase -i HEAD~4'

GitHubssh で接続できるようにする

基本的に公式のドキュメントを見ながら設定すればOK
新しい SSH キーを生成して ssh-agent に追加する - GitHub Docs

SSH 秘密鍵・公開鍵の作成

ed25519秘密鍵と公開鍵を作成する

$ ssh-keygen -t ed25519 -C "your_email@example.com"
Generating public/private ed25519 key pair.
# 秘密鍵・公開鍵の保存場所とファイル名
Enter file in which to save the key (/Users/<user name>/.ssh/id_ed25519):
# パスフレーズの設定 設定しない場合はそのままエンター
Enter passphrase (empty for no passphrase):
# パスフレーズの確認
Enter same passphrase again:

/Users/<user>/.ssh 配下に id_ed25519id_ed25519.pub が作成される

note. ed25519 が使えない場合は RSA で作成する
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

秘密鍵を読み取り専用にする

$ chmod 600 ~/.ssh/id_ed25519

公開鍵を GitHub に登録する

cf. GitHub アカウントへの新しい SSH キーの追加 - GitHub Docs

  1. GitHub のメニューから Settings を選択
    github
  2. 左メニューから SSH and GPG keys を選択し、New SSH Key ボタンをクリック
    github ssh
  3. Title にどのマシンの公開鍵か分かる名前を設定、
    Key にさっき作成した id_ed25519.pub の内容をコピペで貼り付けて Add SSH key をクリック
    GitHub ssh

SSH の設定

SSHの設定ファイルは /Users/<user>/.ssh/config
ファイルがない場合はファイルを作成する

$ touch ~/.ssh/config

パスフレーズをキーチェーンに記憶して使うようにする

パスフレーズを設定している場合、SSH で接続する際に毎回パスフレーズを聞かれるのでキーチェーンにパスフレーズを保存して使うようにする。
~/.ssh/config に下記内容を追記する

Host *
  UseKeychain yes
  AddKeysToAgent yes # ssh-agent を使用する

GitHub への接続設定

~/.ssh/configGitHub への接続設定を追加する

Host github.com
  HostName github.com
  User <GitHub に登録しているメールアドレス>
  Port 22
  IdentityFile "~/.ssh/id_ed25519" # GitHub 用の SSH 秘密鍵

ssh-agent に秘密鍵を登録する

ssh-agent をバックグラウンドで起動

$ eval "$(ssh-agent -s)"
> Agent pid 12345

秘密鍵ssh-agent に追加

ssh-add -K <秘密鍵> で追加できる

$ ssh-add -K ~/.ssh/id_ed25519

ssh-agent に登録された秘密鍵の確認

$ ssh-add -l 
# 登録されている SSH キーのリストが表示される

GitHub への接続の確認

$ ssh -T git@github.com
Hi KiKiKi-KiKi! You've successfully authenticated, but GitHub does not provide shell access.

successfully なメッセージと GitHub のユーザー名が表示されていれば OK
₍ ᐢ. ̫ .ᐢ ₎ 👌 できた

 
ssh-agent の理解が薄くて調べながら書いてたら記事分割していいくらい長くなってしまったケド、まぁまた見直す事があるでしょうからヨシ!
おわり。


[参考]

まちカドまぞく 6巻やっと読めた!危機管理〜

JavaScrip HTML5 input type="datetime-local" の値を設定したい

JavaScript (React) で <input type="datetime-local" /> の値を設定するメモ

datetime-local の valueyyyy-MM-ddThh:mm の形で指定する

表示される日付と時刻の書式は実際の value とは異なることです。表示される日付と時刻は、オペレーティングシステムからの報告に従ってユーザーのロケールによって書式化されますが、日付や時刻の value は常に yyyy-MM-ddThh:mm の書式です。
cf. <input type="datetime-local"> - HTML: HyperText Markup Language | MDN

e.g. React で扱う例

import dayjs from 'dayjs';
import { useState } from 'react';

const initialDateTime = "2021-04-19 12:00";

const formatDateTimeLocal = (datetimeStr) => {
  return dayjs(datetimeStr).format('YYYY-MM-DDTHH:mm');
};

const DatetimeInput = ({ initialDateTime }) => {
  const [datetime, setDateTime] = useState(
    formatDateTimeLocal(initialDateTime)
  );
  const onChangeHandler = (evt) => {
    setDateTime(evt.currentTarget.value);
  };
  return (
    <input
      type="datetime-local"
      value={datetime}
      onChange={onChangeHandler}
    />
  );
};

日付と時間の間にある T を入れ忘れる <input type="datetime-local" />value が空になる

const initialDateTime = "2021-04-19 12:00";

const DatetimeInput = ({ initialDateTime }) => {
  const [datetime, setDateTime] = useState(initialDateTime);
  const onChangeHandler = (evt) => {
    setDateTime(evt.currentTarget.value);
  };
  return (
    <input
      type="datetime-local"
      value={datetime}
      onChange={onChangeHandler}
    />
  );
};

=> 初期値が空になり反映されない。React のエラーも出ないので気づきにくい。

サンプル

See the Pen datetime-local react by KIKIKI (@kikiki_kiki) on CodePen.

所管

datetime-localvalue のフォーマットが合って無くても React ではエラーも警告も出ず、value が空文字になっていてミスが有るのに気づきにくかったです。
JavaScript で直接 DOM に設定しようとすると警告が出るっぽいです。(調べてない)
timezone の調整の仕方がまだよく分かってないので、気が向いたら調べたい。

昔は type="datetime" だったよな〜って思ったらこっちは廃止になってて、代わりに type="datetime-local" を使ってね。※ 但し対応ブラウザ (ry になってたのですね。

HTML の <input type="datetime"> は日付と時刻 (時、分、秒と小数点以下の秒) に加えてタイムゾーンを入力するコントロールでした。この機能は WHATWG HTML 仕様書 から削除され、もうブラウザーでは対応されていません。
代わりに、ブラウザー<input type="datetime-local"> を実装して (かつ開発者に使用を推奨して) います。
cf. <input type="datetime"> - HTML: HyperText Markup Language | MDN

ちゃんとキャッチアップしていかないと…ってお気持ちになりました。


[参考]

ウマ娘良かった…実質アイカツ!だったな…

今更の Firebase Cloud Firestore 。タイムスタンプ周りのメモ

今更ながら Firebase を使う機会が増えてきて Cloud Firestore のタイムスタンプ周りで何度か同じようなことを調べてしまっているのでメモ。

Cloud Firestore のタイムスタンプ型は Date ではなく firebase.firestore.Timestamp

firebase Cloud Firestore
↑これ。

Cloud Firestore にタイムスタンプ型のデータを保存する方法

🙅 input type="date"input type="datetime-local" の値をそのまま送ってもダメ。

import firebase from 'firebase/app';
import 'firebase/firestore';
const firebaseApp = firebase.initializeApp(FIREBASE_CONFIG);
const db = firebaseApp.firestore();
// ...

const [datetime, setDatetime] = useState('');

const postDataToFirebase = async () => {
  const addedDocRef = await db.collection(COLLECTION_NAME).add({
    datetime: datetime, 
  });
  return addedDocRef; 
};

return (
  <input
    type="datetime-local"
    value="datetime"
    onChange={(evt) => setDatetime(evt.currentTarget.value)}
  />
);

=> String 型のまま Cloud Firestore に登録 されてしまう

🙆 Timestamp 型に変換して送る

firebase.firestore.Timestamp.fromDate メソッドで Timestamp 型に変換できる

import firebase from 'firebase/app';
import 'firebase/firestore';
const firebaseApp = firebase.initializeApp(FIREBASE_CONFIG);
const db = firebaseApp.firestore();
// ...

// Firestore の Timestamp に変換して返す
const timestamp = (datetimeStr) => {
  return firebase.firestore.Timestamp.fromDate(new Date(datetimeStr));
};

const [datetime, setDatetime] = useState('');

const postDataToFirebase = async () => {
  const addedDocRef = await db.collection(COLLECTION_NAME).add({
    datetime: timestamp(datetime), 
  });
  return addedDocRef; 
};

return (
  <input
    type="datetime-local"
    value="datetime"
    onChange={(evt) => setDatetime(evt.currentTarget.value)}
  />
);

₍ ᐢ. ̫ .ᐢ ₎👌

cf. #データ型 Cloud Firestore にデータを追加する | Firebase

Date オブジェクトをそのまま送信しても大丈夫だった

Date オブジェクトをそのまま送信すると Firebase 側でよしなに Timestamp 型に変換してくれるみたいです

  const postDataToFirebase = async () => {
    const addedDocRef = await db.collection(COLLECTION_NAME).add({
-     datetime: timestamp(datetime), 
+     datetime: new Date(datetime),
    });
    return addedDocRef; 
  };

サーバーで処理した時間のタイムスタンプを使う (created_at, updated_at)

firebase.firestore.FieldValue.serverTimestamp() を使えばOK

  // ... 略
  const postDataToFirebase = async () => {
    const addedDocRef = await db.collection(COLLECTION_NAME).add({
      datetime: timestamp(datetime),
+     createdAt: firebase.firestore.FieldValue.serverTimestamp(),
    });
    return addedDocRef; 
  };

cf. #サーバーのタイムスタンプ Cloud Firestore にデータを追加する | Firebase


Cloud Firestore から取得した Timestamp を日付表示する

Cloud Firestore から取得した DocumentData にある Timestamp は seconds というプロパティを持っているが、これを new Date() に渡しても日付がズレてしまう。

new Date(seconds) だと別の日付になってしまう問題

Cloud Firestore 上のデータ

createdAt: 2021年4月16日 16:18:17 UTC+9
dueDate: 2021年4月18日 16:18:00 UTC+9
isDone: false
todo: "HPBtoMe"

Cloud Firestore から取得したオブジェクト

{
  createdAt: t {seconds: 1618557497, nanoseconds: 367000000},
  dueDate: t {seconds: 1618730280, nanoseconds: 0},
  isDone: false,
  title: "HPBtoMe",
}

new Date(seconds) した場合

data.dueDate.seconds; // => 1618730280
new Date(data.dueDate.seconds);
// => Tue Jan 20 1970 02:38:50 GMT+0900

Cloud Firestore 上に登録されている dueDate2021年4月18日 16:18:00 UTC+9 なのですが new Date(seconds) で変換すると 1970年1月20日 という全然異なる日付になってしまいました。なんもわからん…

toDate() メソッドを使う

Timestamp class
toDate(): Converts a Timestamp to a JavaScript Date object. This conversion causes a loss of precision since Date objects only support millisecond precision.
Timestamp class | Firebase

import dayjs from 'dayjs';
import firebase from 'firebase/app';
import 'firebase/firestore';
const firebaseApp = firebase.initializeApp(FIREBASE_CONFIG);
const db = firebaseApp.firestore();
// … 

const [todoList, setTodoList] = useState([]);

const getTodoFromFirebase = async () => {
  const items = await db
    .collection(COLLECTION_NAME)
    .orderBy('dueDate')
    .get();
  setTodoList(items.items.map((item) => {id: item.id, ...item.data()}));
};

//...

return (
  <ul>
    {todoList?.map((todo) => {
      const dueDate = dayjs(todo.dueDate.toDate()); // ← ココ
      return (
        <li key={todo.is}>
          <span>{todo.title}</span>
          <time datetime={dueDate.format('YYYY-MM-DDTHH:mm')}>
            {dueDate.format('YYYY-MM-DD')}
          </time>
        </li>
      );
    }}
  </ul>
)

₍ ᐢ. ̫ .ᐢ ₎👌 ヨシ!

所管

Firebase ドキュメント と ドキュメンテーションが別になってるのまじ探しにくいから何とかしておくれ… クラスとかメソッドとか書いてるドキュメンテーションは自動的によしなに日本語翻訳してくれるんだけど、メソッド名まで日本語に翻訳されちゃうから困っちゃうんよね…

とはいえ、だいぶ Firebase と仲良くなれてきた気がします!
そう。4/18 は僕の誕生日なのでみなさん祝ってください!!
欲しいものは時間と知識と不労所得です。ヨロシクオネガイシマス!!!!

干し芋


[参考]

Firestore はこれが良いと聞きました!

アマノ タイムスタンプ PIX-200

アマノ タイムスタンプ PIX-200

  • 発売日: 2008/01/09
  • メディア: オフィス用品