狛ログ

2019年8月16日金曜日

node.jsでの日付時刻処理(moment.jsを使ってみる)

8月 16, 2019

オフィス狛 技術部のJoeです。

node.js(JavaScript)では日付時刻の扱いが難しく、特に文字列の時刻などを比較や計算するときはいつも調べているので、備忘録を兼ねてブログに書いておこうと思います。
また、日付時刻操作ではmoment.jsという便利なライブラリがあるので、同じ処理をmoment.jsでも書いてみます。

① 時刻(文字列)の比較と差分

【ライブラリを使用しない場合】
// Dateオブジェクトを生成
const dateTime1 = new Date('2019-08-01 09:00');
const dateTime2 = new Date('2019-08-01 14:00');

// 大小確認
if (dateTime1 < dateTime2) {
    処理;
}

// 一致確認の場合は「getTime()」でミリ秒形式に変換する
if (dateTime1.getTime() === dateTime2.getTime()) {
    処理;
}

// 差分算出の場合も「getTime()」でミリ秒形式に変換して計算、結果のミリ秒を欲しい単位に計算する
const diffTime = dateTime2.getTime() - dateTime1.getTime(); // ミリ秒で差分を算出
const diffSecond = Math.floor(diffTime / 1000 / 60); // 結果のミリ秒を分に変換
console.log(diffSecond); // 300(分)


【moment.jsを使用した場合】
const moment = require('moment');

// momentオブジェクトを生成
const dateTime1 = moment('2019-08-01 09:00');
const dateTime2 = moment('2019-08-01 14:00');

// 比較(<:isBefore  >:isAfter  <=:isSameOrBefore  >=:isSameOrAfter)
if (moment(dateTime1).isBefore(dateTime2)) {
    処理;
}

// 一致(第2パラメータで年から比較したい単位までを指定可能)
if (moment(dateTime1).isSame(dateTime2, 'minute')) { // 年~分までの一致確認
    処理;
}

// 差分(第2パラメータで取得したい差分の単位を指定可能)
const diffTime = dateTime2.diff(dateTime1, 'minutes'); // 差分を分で取得
console.log(diffTime); // 300(分)


② UTCからJSTに変換

【ライブラリを使用しない場合】
文字列の日時はUTCの時間と仮定しています。
// Dateオブジェクトを生成
const dateTime1 = new Date('2019-08-01 09:00'); // UTCの日時と仮定しています
// ミリ秒にして9時間(32,400,000ミリ秒)足す
dateTime1.setTime(dateTime1.getTime() + 1000 * 60 * 60 * 9);
console.log(dateTime1);  // Thu Aug 01 2019 18:00:00 GMT+0900 (日本標準時)


タイムゾーンを扱う場合は、「moment-timezone」を使います。
【moment.jsを使用した場合】
const momentTimezone = require('moment-timezone');

// UTCのmomentオブジェクトを生成
const dateTimeUtc = momentTimezone.tz('2019-08-01 09:00:11', 'UTC');
// JSTに変換(フォーマットも併せて変換)
const dateTimeJst = momentTimezone(dateTimeUtc).tz('Asia/Tokyo').format('YYYY/MM/DD HH:mm:ss');
console.log(dateTimeJst); // 2019/08/01 18:00:11



ご紹介したmoment.jsの機能はほんの一部ですので、日付時刻操作で悩んだらぜひ使ってみてください。


2019年8月3日土曜日

テンプレート内のclass属性を動的に変える(Angular)

8月 03, 2019

オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。

今回はAngularの軽い小ネタを紹介します。

テンプレート(html)内のclass属性を動的に変えたい、という事はよくあると思います。
特に、入力項目にエラーがあった場合のエラーメッセージ、などがそうですね。

(1)ngIfを使った方法

まずは、ngIfを使った方法から。

<div *ngIf="loginIdInvalid; else loginIdValidBlock" class="form-label alert alert-danger">
使用出来ないログインIDです。
</div>
<ng-template #loginIdValidBlock>
 <div class="form-label correct correct-info">
 使用可能なログインIDです。
 </div>
</ng-template>

「loginIdInvalid」がコンポーネント側(TypeScript側)で定義している変数で、エラーの場合、trueになると思ってください。
これをclass属性を動的に変えているか、と言われると微妙ですが、結果的にclass属性を使い分けている事になります。
困った時の「ngIf」ってやつですね。

(2)[class.xxxxx]を使った場合

次は、[class.xxxxx]を使った場合です。

<div class= "form-label"
       [class.alert]="loginIdInvalid"
       [class.alert-danger]="loginIdInvalid" 
       [class.correct]="!loginIdInvalid"
       [class.correct-info]="!loginIdInvalid">
{{ message }}
</div>

[class.xxxxx]の「xxxxx」にクラス名を指定し、そのクラスを使用するかどうかが、イコールの後ろの条件式(trueかfalseが返却されるもの)となります。
より簡潔にする為、メッセージは変数にして、コンポーネント側(TypeScript側)で設定するようにしました。
「form-label」は正常でもエラーでも共通して使うので、htmlのclass属性として切り出しました。
ちょっと冗長な気もしますが、良く使用されている手法かと思います。

(3)[ngClass]を使った場合

続いて、[ngClass]を使った場合です。

<div class= "form-label"
       [ngClass]="{'alert alert-danger' : loginIdInvalid, correct correct-info' : !loginIdInvalid}">
{{ message }}
</div>

[ngClass]は、クラスを複数一気に指定できます。連想配列形式で「{'xxxx' : '1111', 'yyyy' : '2222'}」のように設定します。
個人的には一番良く使うのですが、正直、こうして他と比べると、ちょっと見難いと言うか、テンプレート側が複雑になるのは、あまり良くないなぁ、と感じています。

(4)[class]を使った場合

最後に、[class]を使った場合です。
[class]を使う場合、コンポーネント側(TypeScript側)にも少しロジックを書く必要があります。
まずはテンプレート側の設定です。

<div [class]="loginIdClass">
{{ message }}
</div>

続いて、コンポーネント側(TypeScript側)の設定です。
get loginIdClass() {
  return this.loginIdInvalid
    ? 'form-label alert alert-danger'
    : 'form-label correct correct-info';
}

テンプレート側はだいぶスッキリしました。実はこの方式は個人的にはあまり使っていなくて、
今回、ブログにする為に使ってみたのですが、割と良いですね。
ただ、htmlのclassタグを同時に使用出来ないので、共通的のクラス(form-label)の記述を敢えて複数回記載することの面倒さと、本来はhtml、つまり画面表示に関わるclass属性内の文字列をコンポーネント側(TypeScript側)に記載している、と言う気持ち悪さは少し残ります。

以上となります。

それでは、良いAngularライフを!


2019年8月2日金曜日

Illustratorのトレース機能で出来るだけ楽にロゴをトレスする。

8月 02, 2019

こんにちは、オフィス狛 デザイン部のSatoです。

今回は、Illustratorを使ってjpgやpngのロゴなどの簡単な画像を簡単にトレースする方法をご紹介したいと思います。(Illustrator使ってる方はみんな知ってる気でいたんですが意外と知らない方も多いようなので)
調節は必要ですが、ペンツールでトレースするよりも早くトレースできるので時短になりますよ!


今回使用する画像です。(架空のサービスのロゴマークです。)

まずこの画像をイラレで読み込みます。
画像を選択した後、コントロールパネルの「画像トレース」をクリックします。


トレース処理が終了後、コントロールパネルの「プリセット」を変えたりしていい感じのプリセットを探します。
一番元画像に近いプリセットを選択後、コントロールパネルの「拡張」ボタンをクリックすればパスにしてくれます!

単純な画像ならそのまま調整せずに綺麗にトレースしてくれます。


複雑な画像で「画像トレース」機能を使う場合は「ウインドウ」>「画像トレース」を選択して画像トレースパネルで調整しましょう!仕上がりを見ながら作業できるため便利です。


昔フォトショップで描いた鶏の絵をトレースしてみました!
絶対ペンツールでトレースしたくないような無駄にテクスチャなど使った絵を細かく再現してくれましたー!ありがたすぎる。


この方法を使うとアナログのラフスケッチを簡単にパス化したり自分で撮影した写真をトレースしたものを元にアイコンを作れたりして便利です!ぜひこの機能を使ってみてください!

2019年7月30日火曜日

踏み台サーバー(EC2)経由でSQLServer(RDS)にSSH接続する方法(ポートフォワーディング)・MacOS編

7月 30, 2019

オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。

以前、弊社のメンバーが、踏み台サーバー(EC2)経由でSQLServer(RDS)にSSH接続する方法(ポートフォワーディング)・Windows編という記事を書きました。

今回は、MacOSでのやり方について記載しようと思います。
(「ポートフォワーディングとは?」の説明については、Windows版の記事をご覧ください。)
今回の接続イメージは下図の通りです。


前回のWindows版は、踏み台サーバーから直接データベースへ接続していましたが、今回は、踏み台からさらにWebサーバーを経由してデータベースへ接続する事にします。
手順は以下となります。
(1)Webサーバー(EC2)へポートフォワーディングする設定で、踏み台サーバー(EC2)へSSH接続
(2)データベース(RDS)へポートフォワーディングする設定で、(1)のポートフォワーディング状態でSSH接続
(3)上記までのポートフォワーディングした状態でSQLServerにログインしDB操作
※各SSH接続で使う鍵はローカルに持っている事を前提とします。

手順(文章)だけだと、分かり難いですね・・・・ということで、具体的な手順を書いていきます。


(1)Webサーバー(EC2)へポートフォワーディングする設定で、踏み台サーバー(EC2)へSSH接続

まずは、踏み台経由でWebサーバー(EC2)へ接続します。
イメージ図で言うと、下記の赤字の「(1)」の部分になります。

まず、mac標準ツールのターミナルを開き、以下のコマンドを入力し、実行します。
ssh -L 2200:10.0.1.1:22 -i key-hoge-bastion.pem bastionuser@xx.yy.zz.001

それぞれ、説明をしていきます。

「ssh -L 2200:10.0.1.1:22」:
ローカルとリモートを繋ぐ設定になります。この場合、最終的に「localhost:2200」が「10.0.1.1:22」へと繋がる事になります。
localhost側のポートは、使用していないものであれば、何でも構いません。
最終的に接続する先のIP(今回は「10.0.1.1」)はプライベートIPである事に気を付けてください。

「-i key-hoge-bastion.pem bastionuser@xx.yy.zz.001」:
これは踏み台への接続設定です。「-i」の後に、踏み台の鍵を指定し、その後ろに、「接続ユーザー名@パブリックIP or ドメイン」を指定します。

コマンド実行後、ターミナルは踏み台に繋がった状態になっています。
ですので、さらにポートフォワードする場合には、ターミナルを新たに起動する必要があります。

※「ssh -fNL」とする事で、バックグラウンドでコマンドが実行されるので、そのまま同じターミナルを使う事が可能です。ですが、今、どこにポートフォワードしているのか分からなく可能性がありますし、タスクをkillするのも面倒だったりするので、最初の内は、ポートフォワードする単位でターミナルを開くことをお勧めします。


(2)データベース(RDS)へポートフォワーディングする設定で、(1)のポートフォワーディング状態でSSH接続

続いて、Webサーバー(EC2)経由でデータベース(RDS)へ接続します。
イメージ図で言うと、下記の青字の「(2)」の部分になります。


ssh -L 1433:hoge.z6vbrfgt5st.ap-northeast-1.rds.amazonaws.com:1433 -i key-hoge-web.pem webuser@localhost -p 2200

それぞれ、説明をしていきます。

「ssh -L 1433:hoge.z6vbrfgt5st.ap-northeast-1.rds.amazonaws.com:1433」:
ローカルとリモートを繋ぐ設定になります。この場合、最終的に「localhost:1433」がRDSのエンドポイント「hoge.z6vbrfgt5st.ap-northeast-1.rds.amazonaws.com:1433」へと繋がる事になります。
localhost側のポートは、使用していないものであれば、何でも構いませんが、後のことを考えて、1433にしました。

「-i key-hoge-web.pem webuser@localhost -p 2200」:
これは、Webサーバー(EC2)への接続設定です。「-i」の後に、Webサーバー(EC2)の鍵を指定し、その後ろに、「接続ユーザー名@localhost -p (1)で設定したポート番号」を指定します。
ポイントは、接続するのはあくまで「ポートフォワード設定をしたlocalhost」と言うことです。

コマンド実行後、ターミナルはWebサーバー(EC2)に繋がった状態になっています。
今回はこれ以上はポートフォワード設定を追加しないので、ターミナルはこのままにしておきます。


(3)上記までのポートフォワーディングした状態でSQLServerにログインしDB操作

ここまで来たら後はデータベースへの接続のみです。
今回は、Azure Data Studioを使って、接続します。

すでに、「localhost:1433」は、「踏み台→Webサーバー」を経由して、「endpoint:hoge.z6vbrfgt5st.ap-northeast-1.rds.amazonaws.com」に繋がっている状態なので・・・


上記のように、接続先を「localhost」(Azure Data Studioはデフォルト1433ポートを使用するので、1433は省略可能)として、ユーザー名とパスワードを入力すれば、無事に接続出来ると思います。

以上となります。今回はSQLServerに限定しましたが、他のDBサーバーでも、基本的な流れは変わらないと思います。


2019年7月29日月曜日

C#でListの多次元化をやってみる。

7月 29, 2019

オフィス狛 技術部のHammarです。

C#で開発中に、ある処理で値を多次元で持たせる必要があり、最初は配列で多次元化を考えたのですが、処理内容的にListを使っているので、Listで多次元化を行ってみました。
php等で配列の多次元はよく行いますが、C#でかつListで行ったことがなかったので、いろいろ調べつつ、自分への備忘録も兼ねて今回記載しようと思います。

まず基本的なListでの動きですが、通常Listに値をセットする場合等は以下のように記述すると思います。
var list = new List<string>();
list.Add("みかん");
list.Add("りんご");
list.Add("バナナ");

上記は1次元Listなので、そのまま
list[0]=>"みかん"
list[1]=>"りんご"
list[2]=>"バナナ"
というような感じで値が入ります。

で、多次元Listですが、基本的には2次元Listができればあとは応用という感じなので、一旦わかりやすく2次元Listを作ってみたいと思います。
例えば以下のようなphpの多次元配列のような感じでデータを持ちたい場合があるとします。
    [0]=>{
        [0]=>"みかん"
        [1]=>"orange"
    }
    [1]=>{
        [0]=>"りんご"
        [1]=> "apple"
    }
    [2]=>{
        [0]=>"バナナ"
        [1]=> "banana"
    }

上記を2次元Listにするには以下のように記述します。
var list = new List<List<string>>()
list.Add(new List<string>());
list[0].Add("みかん");
list[0].Add("orange");
list[1].Add("りんご");
list[1].Add("apple");
list[2].Add("バナナ");
list[2].Add("banana");
結果上記でいくと例えば
list[0][1]=>"orange"
list[2][0]=>"バナナ"
がデータとしてセットされていることになります。

Listの<>内にはクラスも入れる事ができるということなので、多次元化ができるということらしいですね。
なので、3次元、4次元としたい場合(そんなにないと思いますが)、さらにListの<>を入れ子にしていけば可能になります。

あと1次元Listと違って少し注意したいのが、Listに追加するときにはListの中もnewしてインスタンスする必要があります。自分はここで少しハマりました。。

以上のような感じで、Listを多次元化して処理を行う場合に参考になればと思います。

2019年7月26日金曜日

ローカルにあるhtmlファイルでChromeの拡張機能を使う設定。

7月 26, 2019
こんにちは、オフィス狛 デザイン部のSatoです。

今回は、ほんの小技なのですが、ローカルにあるhtmlファイルをChromeで開いた際に、拡張機能を使う方法(設定)です。

何の設定もしていない状態だと、Chromeでローカルファイルを開いた時には拡張機能が使えないので、少々不便です。
私はコーディング中のページ全体を拡張機能でスクリーンショットを撮りたい時があるので、結構困っていました。

コーディング中でも拡張機能が使いたいと思う方は、私以外にもいらっしゃると思いますので設定方法をご紹介します。

拡張機能のアイコンバーを右クリックして、「拡張機能を管理」をクリックし、詳細設定画面に遷移します。

「ファイルの URL へのアクセスを許可する」という項目があるのでONにするとローカルファイルをChromeで開いた際も拡張機能を使えるようになります。

ただ、セキュリティ的に不安のある拡張機能では使わないようにした方が良いかと思います。
(ですので「ファイルの URL へのアクセスを許可する」をONする際は、拡張機能のセキュリティ要件を確認し、慎重に判断してください)

2019年7月5日金曜日

Amazon ConnectとLambdaで電話をかける ③Lambda関数の作成と、④実行

7月 05, 2019

こんにちは、オフィス狛 モバイル開発担当 Aika-yuy です。
今回の投稿は、 AmazonConnectとLambdaで任意の番号に電話をかける方法をご紹介します。









AmazonConnectはコールセンターをメインとして、簡易に作成できるというものなので、
受電する記事をよく見かけますが、架電方法の記事は少なかったので記事にしました。




難しそうに見えますが、簡単で短時間で作成できますので試してみてください。
こちらの4ステップで紹介していきます。

①Amazon Connectで電話番号、お問い合わせフローの作成
②IAMでロールを作成
③Lambda関数の作成← 今回はこちら
④実行!!← 今回はこちら

 

③Lambda関数の作成

今回はいよいよ、Lambda関数からスマフォに電話をかけてみます! とっても簡単なので、あと少し頑張りましょう。

〜必要なもの〜

1、①で作成した電話番号
2、①で作成したお問い合わせフローのインスタンスID、リージョン名、コンタクトフローID
3、②で作成した、ロール
4、任意の電話番号


AWSにログイン後、Lambdaを選択します。
ページ遷移後、関数の作成ボタンを押してください。
下の画像のように入力選択していきます。
1.関数名に任意の関数名をつけてください。
2.実行ロールを既存のロールを使用するを選択してください。
3.②IAMでロールを作成で、作成したロールを選択してください。
※作成したロールがすぐに反映されないことがあるので、作成したロールが見つからない場合は少し時間をおいてからもう一度試してみてください。
4.関数を作成ボタンを押す

それではいよいよ関数を作っていきましょう!

exports.handler = (event) => {
     
    // import entire SDK
    var AWS = require('aws-sdk');
 
    var connect;
    // create amazon connect object
    // ①で作成したお問い合わせフローのリージョン名を入力してください。
    connect = new AWS.Connect({apiVersion: '2017-08-08', region:"ap-northeast-1"});
 
    // create API request parameter
    var params = {
      // ①で作成したお問い合わせフローのコンタクトフローID
      ContactFlowId: "XXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
      // 今回かける先の電話番号
      DestinationPhoneNumber: "XXXXXXXXXXXXXX",
      // ①で作成したお問い合わせフローのインスタンスID
      InstanceId: "XXXXXXXXXXXXXXXXXXXXXX",
      // かける元の電話番号(作成した電話番号)
      SourcePhoneNumber: "+8XXXXXXXXXXX"
    };
  
  // call API with parameter
  console.log("開始!!");
  var calling = connect.startOutboundVoiceContact(params, function(err, data) {
    if (err) {
      console.log(err);
    } else {
      console.log("終了!!電話を切る");
    }
  });
  return calling;
};


これで完成です!

④実行!!

それではいよいよ電話をかけてみます。
Lambdaのページの一番上、右にあるテストボタンを押してください。

任意の電話番号に、電話がかかれば成功です。

意外と簡単に作成できましたね。
アレクサから電話したり色々できそうで、夢が広がりますね。
次回はアプリ(ios)から電話をかけるをやっていきます。