mixin timeOptions()
option(value="14") UTC +14
option(value="13") UTC +13
option(value="12.75") UTC +12:45
option(value="12") UTC +12
option(value="11") UTC +11
option(value="10.5") UTC +10:30
option(value="10") UTC +10
option(value="9.5") UTC +9:30
option(value="9") UTC +9
option(value="8.75") UTC +8:45
option(value="8.5") UTC +8:30
option(value="8") UTC +8
option(value="7") UTC +7
option(value="6.5") UTC +6:30
option(value="6") UTC +6
option(value="5:75") UTC +5:45
option(value="5.5") UTC +5:30
option(value="5") UTC +5
option(value="4.5") UTC +4:30
option(value="4") UTC +4
option(value="3.5") UTC +3:30
option(value="3") UTC +3
option(value="2") UTC +2
option(value="1") UTC +1
option(value="0" selected) UTC +0
option(value="-1") UTC -1
option(value="-2") UTC -2
option(value="-3") UTC -3
option(value="-3.5") UTC -3:30
option(value="-4") UTC -4
option(value="-5") UTC -5
option(value="-6") UTC -6
option(value="-7") UTC -7
option(value="-8") UTC -8
option(value="-9") UTC -9
option(value="-9.5") UTC -9:30
option(value="-10") UTC -10
option(value="-11") UTC -11
option(value="-12") UTC -12
mixin timeFormatOptions
option(value="YYYY/M/D H:mm:ss") 2008/5/1 2:00:00
option(value="ddd, D MMM YYYY HH:mm:ss ZZ") Thu, 1 May 2008 02:00:00 +0900
option(value="ddd MMM D HH:mm:ss ZZ YYYY") Thu May 1 02:00:00 +0900 2008
option(value="DDD MMM DD YYYY HH:mm:ss [GMT]ZZ") Thu May 01 2008 02:00:00 GMT+0900
option(value="X") Unix timestamp
option(value="x") Unix ms timestamp
.col-xs-12.col-md-4
.input-field
h2 input time:
.col-xs-12.convert-from
.row
form.form-inline(onsubmit="return false;")
.input-group
span#time-from.input-group-addon
span.glyphicon.glyphicon-time
input.form-control#convert-from(type='text', placeholder='input time')
span.input-group-btn
button.btn.btn-default.input-now(type="button") Now
p.help-block
| e.g.
br
| 2016/12/31 1:23:45
br
| 2016, 12, 31 1:23:45 PM
br
| Dec 31, 2016 1:23:45
br
| 1483115025
br
| 1483115025000
.row
form.form-inline
label timezone:
select.form-control.input-time-diff
+timeOptions()
.col-xs-12.col-md-6
.output-field
h2 result:
.col-xs-12.convert-to
.row
p.result
//| 2016/11/18(Fri) 21:27:38
.row
form.form-inline
label timezone:
select.form-control.output-time-diff
+timeOptions()
label format:
select.form-control.output-time-format
+timeFormatOptions()
@use postcss-simple-vars;
@use postcss-nested;
body {
margin: 20px;
}
.input-field {
margin-bottom: 40px;
/* clearfix */
&:after{
content: '';
display: block;
clear: both;
}
.row:not(:nth-last-of-type(1)) {
margin-bottom: 10px;
}
}
.output-field {
/* clearfix */
&:after{
content: '';
display: block;
clear: both;
}
}
h2 {
color: #ccc;
font-size: 1em;
}
#convert-from {
width: 220px !important;
}
.form-inline {
/* 最後の要素でなければマージンをあける */
label:not(:nth-last-of-type(1)) {
margin-right: 1em;
}
}
/* 出力結果 */
.result {
font-size: 3em;
}
let mediator = _.extend({}, Backbone.Events);
namespace EVENT {
SUBMIT: 'submit'
};
class TimeModel extends Backbone.Model {
inputTime: string; // 入力された時間
inputTimeDiff: number; // 入力された時間の時差
inputTimeMoment: Moment; // inputTimeとinputTimeDiffから生成したMoment←CodePenだと型定義はこれで大丈夫なん??
outputTime: number; // 出力する時間(ミリ秒)
outputTimeDiff: number; // 出力する時間の時差
outputTimeMoment: Moment; // outputTimeとoutputTimeDiffから生成したMoment←CodePenだと型定義はこれで大丈夫なん??
outputTimeFormat: string|null; // 出力する時間のフォーマット
isValid: boolean; // 入力された時間が日時のフォーマットになっているか
initialize (attributes?: any, options?: any) {
_.bindAll(this,
"updateTime"
);
this.listenTo(this, "change:inputTime", this.updateTime);
this.listenTo(this, "change:inputTimeDiff", this.updateTime);
this.listenTo(this, "change:outputTimeDiff", this.updateTime);
this.updateTime();
// // TEST
// this.listenTo(this, 'change', function () {
// console.log(this.get('inputTime'), this.get('inputTimeDiff'), this.get('outputTimeMoment').format('YYYY/MM/DD HH:mm:ss'), this.get('outputTime'), this.get('outputTimeDiff'));
// });
}
defaults() {
return {
inputTime: 0,
isValidDate: true
}
}
updateTime(): void {
const inputTime = this.get('inputTime');
const inputTimeDiff = this.get('inputTimeDiff');
var format = ''; // 時刻フォーマット
if (inputTime.match(/^\d{10}$/)) {
// unix timestamp
format = 'X';
}
else if (inputTime.match(/^\d{13}$/)) {
// unix ms timestamp
format = 'x';
}
// unix timestampの場合utcOffsetが効かない?
const inputTimeMoment = moment(inputTime, format).utcOffset(inputTimeDiff, 'hours');
const outputTimeDiff = this.get('outputTimeDiff');
const outputTimeMoment = inputTimeMoment.utcOffset(outputTimeDiff * 60);
this.set({
outputTime: parseInt(outputTimeMoment.format('x')),
outputTimeMoment,
isValid: outputTimeMoment.isValid()
});
}
}
/**
* 入力フォーム
*
*/
class InputFormController extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'onSubmit'
);
}
events(): Backbone.EventsHash {
return {
"submit form": this.onSubmit
}
}
onSubmit (e: Event): void {
e.preventDefault();
mediator.trigger(EVENT.SUBMIT);
}
}
class InputFieldView extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'onChangeValid'
);
this.listenTo(this.model, 'change:isValid', this.onChangeValid);
}
onChangeValid (): void {
if (this.model.get('isValid') === true) {
this.$el.removeClass('has-error');
}
else {
this.$el.addClass('has-error');
}
}
}
/**
* 時間入力フォーム
*
*/
class InputTimeController extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'onChange'
);
this.listenTo(mediator, EVENT.SUBMIT, this.onChange); // 送信された
}
events(): Backbone.EventsHash {
return {
"change": this.onChange
}
}
onChange (): void {
this.model.set({
inputTime: this.$el.val()
});
}
}
/**
* 時間入力フォーム
*
*/
class InputTimeView extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'onUpdate'
);
this.listenTo(this.model, 'change:inputTime', this.onUpdate);
}
onUpdate (): void {
const inputTime = this.model.get('inputTime');
// 入力値とmodelの値に差があった場合、modelの値に合わせる
if (inputTime !== this.$el.val()) {
this.$el.val(inputTime);
}
}
}
class TimeNowController extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'onClick'
);
}
events(): Backbone.EventsHash {
return {
"click": this.onClick
}
}
onClick (e): void {
e.preventDefault();
const now = getNow();
this.model.set({
inputTime: now.time,
inputTimeDiff: now.diff
});
}
}
/**
* 時差の選択
*
*/
class TimeDiffController extends Backbone.View<TimeModel> {
target: string; // 'input' or 'output'
initialize (options?: Backbone.ViewOptions<TimeModel>) {
this.target = options.target;
_.bindAll(this,
'onChange'
);
if (this.target === 'input') {
this.listenTo(mediator, EVENT.SUBMIT, this.onChange); // 送信された
}
}
events(): Backbone.EventsHash {
return {
"change": this.onChange
}
}
onChange (): void {
const value = parseFloat(this.$el.val());
if (this.target === 'input') {
this.model.set({
inputTimeDiff: value
});
}
else if (this.target === 'output') {
this.model.set({
outputTimeDiff: value
});
}
}
}
/**
* 時差の選択
*
*/
class TimeDiffView extends Backbone.View<TimeModel> {
target: string; // 'input' or 'output'
param: string; // 対象のmodelの値
initialize (options?: Backbone.ViewOptions<TimeModel>) {
this.target = options.target;
_.bindAll(this,
'onUpdate'
);
let param: string; // listenToする変数名
if (this.target === 'input') {
param = 'inputTimeDiff';
}
else {
param = 'outputTimeDiff';
}
this.param = param;
this.listenTo(this.model, `change:${this.param}`, this.onUpdate);
}
onUpdate (): void {
const value = this.model.get(this.param);
// 入力値とmodelの値に差があった場合、modelの値に合わせる
if (parseFloat(this.$el.val()) !== value) {
this.$el.val(value);
}
}
}
class OutputTimeView extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'render'
);
this.listenTo(this.model, 'change:outputTime', this.render);
this.listenTo(this.model, 'change:outputTimeDiff', this.render);
this.listenTo(this.model, 'change:outputTimeFormat', this.render);
this.render();
}
render(): void {
const time = this.model.get('outputTimeMoment')
const format = this.model.get('outputTimeFormat');
this.$el.html(time.format(format));
}
}
/**
* 出力時間の形式
*
*/
class TimeFormatView extends Backbone.View<TimeModel> {
initialize (options?: Backbone.ViewOptions<TimeModel>) {
_.bindAll(this,
'onChange'
);
}
events(): Backbone.EventsHash {
return {
"change": this.onChange
}
}
onChange (): void {
this.model.set({
outputTimeFormat: this.$el.val()
});
}
}
/**
* 現在時間と時差を取得
*
* @return .time 現在時間
* @return .diff 時差
*/
function getNow(): string[] {
const now = new Date();
const currentTimeZoneOffsetInHours = now.getTimezoneOffset() / -60; // 現在時間の時差
return {
time: now.toString().replace(/\sGMT[^$]+/i, ''),
diff: currentTimeZoneOffsetInHours
};
}
{
const $convertFrom = $('#convert-from'); // 時間入力フォーム
const $inputTimeDiff = $('.input-time-diff'); // 入力時間の時差
const $outputTimDiff = $('.output-time-diff'); // 出力時間の時差
const $outputTimeFormat = $('.output-time-format'); // 出力時間の形式
const now = getNow(); // 現在時間と時差
// 入力時間に現在の時間を設定
$convertFrom.val(now.time); // GMT〜を削除したローカル時間
$inputTimeDiff.val(now.diff);
// TODO 入力時間の時差を設定する
const timeModel = new TimeModel({
inputTime: $convertFrom.val(),
inputTimeDiff: parseFloat($inputTimeDiff.val()),
outputTimeDiff: parseFloat($outputTimDiff.val()),
outputTimeFormat: $('.output-time-format').val()
});
// TODO cookieの設定で、時差、出力後のフォーマットを設定する
new InputFormController({
model: timeModel,
el: '.input-field form'
});
new InputFieldView({
model: timeModel,
el: $('.input-field').find('.input-group').get(0)
});
new InputTimeController({
model: timeModel,
el: $convertFrom.get(0)
});
new InputTimeView({
model: timeModel,
el: $convertFrom.get(0)
});
new TimeDiffController({
model: timeModel,
el: $inputTimeDiff.get(0),
target: 'input'
});
new TimeDiffView({
model: timeModel,
el: $inputTimeDiff.get(0),
target: 'input'
});
new TimeNowController({
model: timeModel,
el: '.input-now'
});
new OutputTimeView({
model: timeModel,
el: '.result'
});
new TimeDiffController({
model: timeModel,
el: $outputTimDiff.get(0),
target: 'output'
});
new TimeDiffView({
model: timeModel,
el: $outputTimDiff.get(0),
target: 'output'
});
new TimeFormatView({
model: timeModel,
el: $outputTimeFormat.get(0)
});
// 入力エリアにフォーカスを設定する
// document.getElementById('convert-from').focus();
}
Also see: Tab Triggers