在宅での仕事で作業に集中するために効果があった工夫のメモ。

ここ1ヶ月くらい在宅で仕事をすることが多かったので、自宅でも安定して仕事に集中するために効果があった工夫をメモ。

工夫を一言でいうと

工夫を一言でいってしまうと「作業環境を会社でのそれに近づける」これに尽きる。
本来はプライベートモードであるのが当然の空間である自宅を、仕事モードに入っている時の環境 = 会社での作業環境に近づけることによって自然と仕事モードに入ることができ、それを持続することができる。

工夫の具体的なところ

ラジオをかける

自分の会社では常にラジオがかかっているので、在宅で仕事するときにもラジオをかけるようにしている。
会社では常に J-Wave がかかっているので、当然自宅でも常に J-Wave をかけている。
J-Wave は平日の帯番組が決まっているため、そのときにかかっている番組でだいたいの時間帯が肌感覚で分かるのだが、この「肌感覚でだいたいの時間帯が分かる」というのも会社と自宅とで同じ体験となるため、仕事に集中しやすくなるのに一役買っているようだ。

食事

普段は就業開始時間の少し前に出社して、コンビニで買ってきたおにぎりやサンドイッチを自分の席で食べている。
在宅での仕事を始めた頃は朝食を自炊していたのだが、それをやめて普段と同じような時間帯にコンビニで食事を買い、普段と同じような時間帯に食べるようにしたところ、とても仕事モードに入りやすくなった。
当然、コンビニで買うのも普段と同じようにおにぎりやサンドイッチだ。

飲み物

普段はコンビニで朝食と一緒にコーヒーを買ってきてそれを飲みながら仕事をしている。
そこで、在宅での仕事でも同じようにコンビニで朝食と一緒にコーヒーを買ってきて飲むようにしたところ、とても仕事モードに入りやすくなった。
熱いコーヒーの香りが部屋に漂っているとリラックスするとともに仕事に向き合う気力も湧いてくる。

小道具

普段はちょっとしたタスクを管理したりアイデアをかき混ぜるために筆記用具を使っている。
実際に使っているのはコンビニで売っている大学ノートをサイズ違いで2冊と万年筆 *1 なのだが、在宅で作業するときは会社から持ち帰って自宅でも使うようにした。
仕事そのものをしているときは how つまり「どうやって仕様を実現するか」といったことに意識が向いているが、筆記用具を使っているときは why や what つまり「なぜその作業をしているのか」「何の作業をしているのか」ということに意識が向くようで、それが仕事モードを持続することにつながっているようだ。

在宅での仕事で作業に集中するためにどれくらい効果があったのか

今の作業環境を作ったことで会社と完全に同じか、ときによって会社よりも作業に集中できるようになった。
会社ではどうしてもノイズが発生してしまうところが自宅では発生しないのでより集中しやすいのかもしれない。というか、自宅で仕事をしていると集中しすぎて定時が過ぎたころにはぐったりしていることが多い。

今後

さらにいろいろ試してみて、より作業に集中しやすい工夫を見つけていきたい。

*1:といっても高いものではなく実用性重視のもの

ipa ファイルからプロビジョニングプロファイルの期限を確認するメモ。

ipa ファイルからプロビジョニングプロファイルの期限を確認するメモ。

したいこと

ipa ファイル (iOS のアプリ) しかない状態でプロビジョニングプロファイルの有効期限を確認したい。
中間ファイルとかは作りたくない。

確認する方法

プロビジョニングプロファイルの情報は ipa ファイルのなかの Payload/<アプリ>.app/embedded.mobileprovision に記述されているので、それを確認すればよい。
embedded.mobileprovision の中身は XMLExpirationDate の次に現れる 要素がプロビジョニングプロファイルの有効期限を示している。

実際の確認

ざっくりと確認

こんな感じで確認できた *1

$ unzip -p <ipa ファイル> Payload/<アプリ>.app/embedded.mobileprovision \
	 | strings \
	 | LC_ALL=C sed -n -e '/ExpirationDate/ {n;p;}' \
	 | sed -e 's/<\/*date>//g'
2019-12-14T00:00:00Z

embedded.mobileprovision を XML として確認

embedded.mobileprovision の中身は XML なので XML として扱っても同じように確認できる。

$ unzip -p <ipa ファイル> Payload/<アプリ>.app/embedded.mobileprovision \
	| strings \
	| LC_ALL=C sed -n -e '/^<data/d' -e '/^<?xml/,/^<\/plist>/p' \
	| xmllint --xpath '//key[text()="ExpirationDate"]//following-sibling::date[1]/text()' -
2019-12-14T00:00:00Z

利用できる iOS シミュレーターをざっくり確認するときのメモ。

利用できる iOS シミュレーターをざっくり確認するときのメモ。

Xcode の Devices & Simulators から確認できるけど、普段 Xcode を使わないのでコマンドラインからざっくり確認したい。

こんなときは Xcodeコマンドラインツールである simctl コマンドを使うと簡単に確認できる。

$ xcrun simctl list devices
== Devices ==
-- iOS 11.2 --
    iPhone 5s (C367044F-AF26-47DE-8444-9F22416C2525) (Shutdown)
    iPhone 6 (2E19BDBE-A762-4115-9582-DAC66FD9B106) (Shutdown)
    iPhone 6 Plus (E08573CC-0879-4312-BC06-E6D40989EB40) (Shutdown)
    iPhone 6s (C2CF2C3B-D776-4D72-B564-E59BD7527058) (Shutdown)
    iPhone 6s Plus (B24A7481-2E12-40DF-85B4-F657E7A7BD3E) (Shutdown)
    iPhone 7 (81425B8B-E722-4BFB-B467-7FF0A87F0151) (Shutdown)
    iPhone 7 Plus (F55C9029-7330-454A-9661-D65FB131F40F) (Shutdown)
    iPhone 8 (1C7D47A9-7E21-41BF-8AB2-8BB2DE28A846) (Shutdown)
    iPhone 8 Plus (65084E57-278A-4268-B37E-CA149D9FE1CB) (Shutdown)
    iPhone SE (80BC4B09-1E76-455A-BC28-125A2C1DBC59) (Shutdown)
    iPhone X (06E64320-B050-44BC-9D59-97B3B0860C43) (Shutdown)
# 省略
-- Unavailable: com.apple.CoreSimulator.SimRuntime.iOS-11-0 --
    iPhone 5s (547BCCDF-AED5-4284-BF4D-4FA20DBB09A1) (Shutdown) (unavailable, runtime profile not found)
    iPhone 6 (B348CE31-10CD-4D92-AB5E-2784BF65C751) (Shutdown) (unavailable, runtime profile not found)
    iPhone 6 Plus (AA4EECE5-BDCD-4B73-84A6-ADEEFF95EC9C) (Shutdown) (unavailable, runtime profile not found)
    iPhone 6s (956995BD-35FB-476D-B17F-F750065EF012) (Shutdown) (unavailable, runtime profile not found)
    iPhone 6s Plus (09FD128D-C32E-488A-81BB-EC4F134A0EE6) (Shutdown) (unavailable, runtime profile not found)
    iPhone 7 (6D0D76B6-57E9-4292-A420-4738E9022EBF) (Shutdown) (unavailable, runtime profile not found)

こんな感じでぞろぞろと出力されるのだが、ランタイムがないなどで利用できないデバイスも出力されるし、自分は iOS 以外のシミュレーターは必要としていないので、このあたりをフィルタリングすると見やすくなりそう。--json オプションを使うと JSON で出力できるので、それを jq コマンドでフィルタしてみる。

$ xcrun simctl list --json devices |
	jq --raw-output '.devices |
		to_entries[] |
		select(.key | startswith("iOS")) |
		.key as $key | .value[] |
		select(.availability == "(available)") |
		.name + ", " + $key'

iPhone 5s, iOS 11.2
iPhone 6, iOS 11.2
iPhone 6 Plus, iOS 11.2
iPhone 6s, iOS 11.2
iPhone 6s Plus, iOS 11.2
iPhone 7, iOS 11.2
iPhone 7 Plus, iOS 11.2
iPhone 8, iOS 11.2
iPhone 8 Plus, iOS 11.2
iPhone SE, iOS 11.2
iPhone X, iOS 11.2
iPad Air, iOS 11.2
iPad Air 2, iOS 11.2
iPad (5th generation), iOS 11.2
iPad Pro (9.7-inch), iOS 11.2
iPad Pro (12.9-inch), iOS 11.2
iPad Pro (12.9-inch) (2nd generation), iOS 11.2
iPad Pro (10.5-inch), iOS 11.2

いい感じ。

カンマから前がデバイスの名前になる *1

Xcode は 9.2、jq は1.5 で確認 *2

*1:simctl はじめいろんなコマンドで指定できる

*2:Xcode は 10.0 とかでも大丈夫

Golang 1.10 + Python 3 の Dockerfile を作ったときのメモ。

Golang 1.10 + Python 3 の Dockerfile を作ったときのメモ。

Golang は 1.10, Python は 3.7 (以降) のバージョン縛りがあって、Golang をベースに Python 3 を入れようとしたらいろいろ面倒くさそうだったので、Python 3 をベースに Golang を入れることにした。

FROM python:3

RUN set -ex && \
		cd /tmp && \
		curl -O https://dl.google.com/go/go1.10.4.linux-amd64.tar.gz && \
		tar -C /usr/local -xzf go1.10.4.linux-amd64.tar.gz && \
		rm /tmp/go1.10.4.linux-amd64.tar.gz

ENV PATH $PATH:/usr/local/go/bin

docker build して動作確認。

root@4c80d3229411:/# go version
go version go1.10.4 linux/amd64

root@4c80d3229411:/# python --version
Python 3.7.0

よさそう。

pt でよく使うオプションのメモ。

pt でよく使うオプションのメモ。

したいこと

  • 単語単位の検索
  • 大小文字を無視
  • 大小文字を無視 (スマートケース)
  • 正規表現での検索
  • 特定のファイルを検索
  • 特定のファイルを除外して検索

単語単位の検索

単語単位で検索したいときは --word-regexp あるいは -w オプションを使う。

$ echo 'abcde
abc' | pt abc
abcde
abc

$ echo 'abcde
abc' | pt --word-regexp abc
abc

大小文字を無視

大小文字を無視したいときは --ignore-case あるいは -i オプションを使う。

$ echo 'abc
Abc' | pt abc
abc

$ echo 'abc
Abc' | pt --ignore-case abc
abc
Abc

$ echo 'abc
Abc' | pt --ignore-case ABC
abc
Abc

大小文字を無視 (スマートケース)

スマートケースで検索したいときは --smart-case あるいは -S オプションを使う。

$ echo 'abc
Abc' | pt --smart-case abc
abc
Abc

echo 'abc
Abc' | pt --smart-case Abc
Abc

$ echo 'abc
Abc' | pt --smart-case ABC

正規表現での検索

正規表現で検索したいときは -e オプションを使う。

$ echo 'abc
xyz' | pt -e 'abc|xyz'
abc
xyz

特定のファイルを検索

特定のファイルだけを検索したいときは --file-search-regexp あるいは -G オプションを使う。

$ cat a.txt
abc

$ cat b.txt
abc

$ cat c.txt
abc

$ pt abc
./c.txt
1:abc

./a.txt
1:abc

./b.txt
1:abc

$ pt --file-search-regexp '[ab].txt' abc
./b.txt
1:abc

./a.txt
1:abc

特定のファイルを除外して検索

反対に特定のファイルを除外して検索したいときは --ignore オプションを使う。

# ファイルは上と同じ

$ pt --ignore '[ab].txt' abc
./c.txt
1:abc

dt に計算結果の日付が無効になったときの調整オプションを追加したメモ。

3/31の1ヶ月後が4/30になったり5/1になったりする 動きをオプションで指定できるようにしたメモ。

dt は5/1になる動きだったのを、4/30になるようにオプションで指定できるようにした。

$ dt "2018/01/31" +1M
2018/03/03


$ dt --adjust-day "2018/01/31" +1M
2018/02/28

こんな感じ。

ただ、複数月を1回で足すときと複数回に分けて足すときとでは最終的な結果が変わることには注意が必要かもしれない。

$ dt --adjust-day "2018/01/31" +2M
2018/03/31

$ dt --adjust-day "2018/01/31" +1M +1M
2018/03/28

github.com

3/31の1ヶ月後が4/30になったり5/1になったりするメモ。

日付計算で月を加算 (減算) して、加算結果の日付が無効になったときの動きのメモ。

書くこと

  • 加算結果が無効な日付になる例
  • 各言語での例
  • 仕様
  • まとめ

加算結果が無効な日付になる例

日付計算で月を加算 (減算) したとき、加算結果の日付が無効になることがある *1
たとえば、3/31に1ヶ月を足すと4/31という無効な日付になるが、プログラミング言語により無効な日付の扱いが変わってくる。
いくつかの言語での例を書いてみる。

各言語での例

# Java
$ jshell
jshell> import java.time.LocalDate;
jshell> LocalDate.of(2018, 3, 31).plusMonths(1);
$2 ==> 2018-04-30

# Ruby
$ irb
irb(main):001:0> require "date"
=> true
irb(main):002:0> Date.new(2018, 3, 31).next_month
=> #<Date: 2018-04-30 ((2458239j,0s,0n),+0s,2299161j)>

# Golang
$ gore -autoimport
gore version 0.3.0  :help for help
gore> time.Date(2018, 3, 31, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0)
2018-05-01 00:00:00 Local

JavaRuby では4月の最後の日である4/30が返されるが、Go では翌月の5/1が返されている。

仕様

各言語の仕様を見てみる。

Java

LocalDate

This method adds the specified amount to the months field in three steps:
1. Add the input months to the month-of-year field
2. Check if the resulting date would be invalid
3. Adjust the day-of-month to the last valid day if necessary
For example, 2007-03-31 plus one month would result in the invalid date 2007-04-31. Instead of returning an invalid result, the last valid day of the month, 2007-04-30, is selected instead.

加算結果の日付が無効になるときは、月の日を有効な最後の日に調整するようだ。

Ruby

instance method Date#

対応する月に同じ日が存在しない時は、代わりにその月の末日が使われます。

Go

Time.AddDate

AddDate normalizes its result in the same way that Date does, so, for example, adding one month to October 31 yields December 1, the normalized form for November 31.

AddDateは、Dateと同じ方法で結果を正規化します。たとえば、10月31日に1か月を追加すると、11月31日の正規化された形式である12月1日が得られます。

まとめ

個人的には、Go のように3/31の1ヶ月後が5/1になるというのは変な感じがするが、4/31という無効な日付は4/30の1日後であるから、4/30の有効な1日後 = 5/1が返されるというのは納得できる。
むしろ、言語やライブラリの場合は仕様にはっきりと書かれているので使う側が気をつければいいが、お客さんや同僚と話しているときにこのあたりの "自然な加算結果" が違っていると、少し苦労しそう。

*1:うるう年が絡むと年の加算などでも同じことが起こる