日付時刻(1)

asctime()、ctime()、gmtime()、localtime()、mktime()、timegm()

標準のCで使える関数ですが、知らない人が多いと思うので紹介しておきます。

#include <time.h>
struct tm {
  int tm_sec;     /* 秒 */
  int tm_min;    /* 分 */
  int tm_hour;  /* 時間 */
  int tm_mday; /* 日 */
  int tm_mon;   /* 月 */
  int tm_year;    /* 年 */
  int tm_wday;  /* 曜日 */
  int tm_yday;   /* 年内通算日 */
  int tm_isdst;   /* 夏時間 */
};
char *asctime(const struct tm *tm);
char *ctime(const time_t *timep);
struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);
time_t mktime(struct tm *tm);
time_t timegm(struct tm *tm);
char *asctime(const struct tm *tm);
char *ctime(const time_t *timep);

日時を表す文字列を「Fri Feb 26 21:37:39 2010」という形式で返します。ctime()が受け取るのは、協定世界時(UTC)1970年1月1日00:00:00からの経過秒数(time()で得られます)です。
この文字列は静的に割り当てられた文字列なのでfree()で解放する必要はありません。しかし、日時を扱う関数を呼ぶと上書きされる可能性があるので注意してください。

struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);

協定世界時(UTC)1970年1月1日00:00:00からの経過秒数(time()で得られます)を受け取り、struct tmの形式に変換します。localtime()はローカルのタイムゾーンに合わせて変換し、gmtime()はUTCのまま変換します。
ここで得られるstruct tmは静的に割り当てられているのでfree()で解放する必要はありません。しかし、日時を扱う関数を呼ぶと上書きされる可能性があるので注意してください。

time_t mktime(struct tm *tm);
time_t timegm(struct tm *tm);

協定世界時(UTC)1970年1月1日00:00:00からの経過秒数(time()で得られます)を返します。
mktime()はtmがローカルタイムゾーンであると解釈し、timegmはUTCであると解釈します。

使い方

#include <stdio.h>
#include <time.h>

int main() {
  time_t clock;
  struct tm *time_ptr;

  time(&clock);

  printf("time: %lu\n",clock);

  // ctime()の使用例
  printf("ctime: %s",ctime(&clock));

  // asctime()、localtime()、mktime()の使用例
  time_ptr=localtime(&clock);
  printf("asctime(localtime): %s",asctime(time_ptr));
  printf("mktime(localtime): %lu\n",mktime(time_ptr));

  // gmtime()、timegm()の使用例
  time_ptr=gmtime(&clock);
  printf("asctime(gmtime): %s",asctime(time_ptr)); // 9時間前
  printf("timegm(gmtime): %lu\n",timegm(time_ptr));

  return 0;
}

コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c

実行結果

time: 1267190498
ctime: Fri Feb 26 22:21:38 2010
asctime(localtime): Fri Feb 26 22:21:38 2010
mktime(localtime): 1267190498
asctime(gmtime): Fri Feb 26 13:21:38 2010    <- UTCなので9時間前
timegm(gmtime): 1267190498

RPGの素人と玄人を見分ける10の方法

  1. オープニングを見て喜ぶのは素人。開発の背景について語り出すのは玄人。readme.txtがオープニングなのがローグライカ
  2. 見た目の美しさを褒めるのは素人。見えない所まで作り込んでいる事を褒めるのは玄人。アスキー文字に萌えるのがローグライカ
  3. 壮大なストーリーを求めるのは素人。自分設定を作るのは玄人。ストーリーがある事を知らないのがローグライカ
  4. 試行錯誤しながら操作を覚えるのは素人。どんな操作か予想がつくのは玄人。とりあえずhjklを打つのがローグライカ
  5. 始まってすぐ死ぬと怒るのは素人。ゾクゾクするのは玄人。疑問に思わないのがローグライカ
  6. 敵を倒したらアイテムを落とすか期待するのは素人。落とす確率を把握しているのは玄人。死体を食べようとするのがローグライカ
  7. どんどん強い装備をそろえていくのは素人。装備縛りをするのは玄人。装備したら能力値が下がって死ぬのがローグライカ
  8. 広い迷宮で敵をうっとうしがるのは素人。効率よく捌いていくのは玄人。食料が来たと喜ぶのがローグライカ
  9. レア装備が手に入って喜ぶのは素人。既に全て揃えているのは玄人。手に入れた直後に死ぬのがローグライカ
  10. エンディングを見て感動するのは素人。二次創作を始めるのは玄人。クリアできる人が殆どいないのがローグライカ

スリープ

プログラムの実行を一時的に休止する関数として、sleep()、usleep()、nanosleep()があります。
sleep()は秒単位、usleep()はマイクロ秒(100万分の1秒)単位、nanosleep()はナノ秒(10億分の1秒)単位で休止できます。

sleep()

#include <unistd.h>
unsigned int sleep(unsigned int seconds);

sleep()は秒単位で休止できます。

使い方
#include <unistd.h>
#include <stdio.h>

int main() {
  unsigned int delay=1;

  printf("sleep(1 sec)\n");
  sleep(delay);
  printf("end\n");
  return 0;
}
コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c

usleep()

#include <unistd.h>
int usleep(useconds_t useconds);

usleep()はマイクロ秒(100万分の1秒)単位で休止できます。

使い方
#include <unistd.h>
#include <stdio.h>

int main() {
  useconds_t delay=1500000;

  printf("sleep(1.5 sec)\n");
  usleep(delay);
  printf("end\n");
  return 0;
}
コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c

nanosleep()

#include <time.h>
struct timespec {
  time_t tv_sec;        /* seconds */
  long   tv_nsec;       /* nanoseconds */
};
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

nanosleep()はナノ秒(10億分の1秒)単位で休止できます。
rgtpで休止する時間を指定します。
シグナルで休止を中断されるとnanosleep()は-1を返し、残り時間をrmtpに保存します。このとき、rmtpがNULLの場合は保存しません。
なお、tv_nsecの上限は999999999となっています。

使い方
#include <stdio.h>
#include <time.h>

int main() {
  struct timespec delay;

  delay.tv_sec=1;
  delay.tv_nsec=500000000;
  printf("sleep(1.5 sec)\n");
  nanosleep(&delay,NULL);
  printf("end\n");
  return 0;
}
コンパイル

プログラムが書かれたファイル名をtest.cとします。

gcc test.c

一度も動かしてないTwitterクライアントがTwitterにブロックされた。何を言っているのか(ry

昨日、Twitterから「規約に反しているから、そちらのクライアントに割り当てたOAuth tokenを無効にした」という旨のメールが来ました。
OAuth tokenというのはTwitterで認証をするために必要な物で、あらかじめTwitter側にクライアントを登録して割り当ててもらいます。
一度も動かしてない(そもそも作ってもいない)のになんでこんな事を言われるのか解らなかったので問い合わせた所、「自動フォロー、フォロー解除は認めてない」との返事が来ました。
別の人と勘違いしているのでは?あるいは、他の人とOAuth tokenが被ってる?という疑念が沸き起こってきますが、こちらでは確認しようがないので、作ろうとしているクライアントの説明をつけて返信しました。
すると、こんな返事が

On first appearance it seemed to be a tool for automated following, but perhaps this was a mis-translation on our part, for that we apologize.

「ぱっと見、自動フォローツールかと思っちゃったよ。意味を取り違えていたみたい、ごめんね」


なん・・・だと・・・?
登録した際にクライアント名を「Group」、説明に「Grouping users」という適当な事を書いていたのが良くなかったみたいです。Twitter向けのアプリケーションを作っている人は気をつけましょう。


追記:友だち探す君もとばっちりを受けてOAuth tokenが無効にされてしまいました。すぐには戻してもらえないみたいで困りものです

同一セッションで複数のアクションを同時に呼べなくなったときの対処法

CakePHPでサイトを構築していると、時間がかかるアクションの実行中に他のアクションが実行できなくなる時があります。
他のページに移動できないだけなら問題ないのですが(むしろ有り難い)、Ajaxで途中経過を別アクション経由で取得したい時等に困ります。
Security.levelをmedium、lowにしている時にこの問題は起き易いのですが、highにしてても起きる時があるので原因は良く判りません。
不可解な現象ですが、セッションをDBに保存するようにしたら解決したのでやり方を書いておきます(CakePHPからDBを使えるようになっていることを前提にしています)。

  1. app/config/core.phpの102行目 「Configure::write('Session.save', 'php');」を「Configure::write('Session.save', 'database');」に変更
  2. app/config/core.phpの110行目 「//Configure::write('Session.table', 'cake_sessions');」を有効にする為に「Configure::write('Session.table', 'cake_sessions');」に変更(「cake_sessions」はセッションを保存する為のテーブル名なので変更しても良い)
  3. app/config/core.phpの116行目 「//Configure::write('Session.database', 'default');」を有効にする為に「Configure::write('Session.database', 'default');」に変更(「default」はapp/config/database.phpでDBの設定を指す変数名。セッションを保存する為に使う設定を指定する)
  4. app/config/sql/sessions.sqlを参考にしてテーブルを作る。dataの型がtextになっているが、セッションデータが大きくなる場合はmediumtextかlongtextにした方が良い

投げ銭として簡単に利用できそうなサービス

プログラマー、デザイナー、ブロガーが手軽に投げ銭を受け取れたらいいなぁ、と思うので、投げ銭として簡単に利用できそうなサービスをまとめてみました。
日本でも欧米の様に投げ銭が普及するといいですね。

はてなポイント

  • 送信できる人:はてなユーザ
  • 受け取る事ができる人:はてなユーザ
  • 交換:楽天スーパーポイント(手数料5%、4000円までは200円)、Amazonギフト券(手数料5%、4000円までは200円)
  • 有効期限:最終利用日から1年
  • 1ポイント1円
  • 送信単位:1ポイント
  • 送信手数料:送信ポイントの5%。送信ポイントが20ポイント未満の場合は1ポイント
  • 送信方法:送信ページ リンク例) https://www.hatena.ne.jp/sendpoint?name=はてなID
  • 購入方法:クレジットカード、ドコモ決済、コンビニ(手数料250円)、ちょコム、イーバンク(手数料無料)、銀行振込み(手数料はユーザ負担)、郵便振替(手数料はユーザ負担)

Amazonギフト券(Amazonのサイトで購入)

  • 送信できる人:Amazonで買い物ができる人
  • 受け取る事ができる人:メールアドレスを持ってる人
  • 有効期限:ギフト券毎に有り
  • 送信単位:500円から5万円
  • 送信手数料:無し
  • 送信方法:購入時に送信先のメールアドレスを指定、購入後、Amazonがメールで送信
  • 購入方法:クレジットカード
  • 注意:外国のAmazonで購入したギフト券は日本のAmazonでは使えない

ぷちカンパ

  • 送信できる人:WebMoneyを持っている人(プリペイドなのでWebMoneyの会員である必要は無し)
  • 受け取る事ができる人:WebMoneyの会員
  • 交換:楽天スーパーポイント(手数料5%)
  • 有効期限:無し
  • 1ポイント1円
  • 送信単位:1ポイント
  • 送信手数料:送信ポイントの5%
  • 送信方法:自サイトに設置した送信ボタン。送信ボタンは会員ページでタグを生成し、設置したい場所に貼付ける
  • 購入方法:たくさんあるので公式ページを御覧下さい。クレジットカード、銀行、コンビニ、PC・ゲームショップ、ネットカフェ

Edy

BitCash

  • 送信できる人:特に制限無し
  • 受け取る事ができる人:特に制限無し
  • 送信方法:BitCashに書いてあるひらがな16文字のコードをメール等で送信
  • 送信単位:送ろうとしているBitCashの残高次第
  • 有効期限:無し
  • 購入方法:たくさんあるので公式ページを御覧下さい。クレジットカード、銀行、郵貯、コンビニ
  • 注意:有効なBitCashのコードが送られてくる保証がない

諸葛亮Bot作りました

諸葛亮集』の内容を呟く諸葛亮Botを作りました。


諸葛亮のtwitter bot


朝10時に一回だけ呟きます。
なお、botの作成には次のサイトを参考にさせて頂きました。


プログラミングができなくても作れるTwitter botの作り方
プログラミングができない人もみんなTwitter Botを作ったらいいよ


他のbotもよろしく!