【Django】datetime.dateで保存された値のUNIXマイクロ秒変換方法と並び替え

【Django】datetime.dateで保存された値のUNIXマイクロ秒変換方法と並び替え

意外と苦戦しました。
中々いい情報を探し出すことが出来なかったからと言うのが一番の理由です。
と言う事で備忘録です。

まずは変換とグラフ作成の完成形です

#models.py

from django.db import models

class Weekly_quantity(models.Model):
    """クローバー観測データ"""
    observation_date = models.DateField(verbose_name='観測日')
    four_leaves = models.IntegerField(verbose_name='4葉枚数')
    memo = models.CharField(verbose_name='気付いた事', max_length=200)
    created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)

    class Meta:
        verbose_name_plural = 'Weekly_quantity'

        def __str__(self):
            return self.star_tdate
#urls.py

from django.urls import path
from . import views

app_name = 'clover'
urlpatterns = [
  path('', views.CloverIndexView, name="clover_index"),
#views.py

import logging
import time
from operator import itemgetter
from django.shortcuts import render
from django.views import generic
from .models import Weekly_quantity
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin

logger = logging.getLogger(__name__)
@login_required

def CloverIndexView(request):
    data = Weekly_quantity.objects.order_by('observation_date').reverse()[:41]

    """データ成形"""
    list_plots = []
    for dt in data:
        list_plots.append([int(time.mktime(dt.observation_date.timetuple())*1000), dt.four_leaves])

    list_plots.sort(key=itemgetter(0))

    params = {
        'title': '四葉数推移',
        'data': data,
        'js': list_plots
    }
    return render(request, 'index.html', params)
#index.html

{% extends "base_site.html" %}
{% if user.is_authenticated %}
{% block title %} Dashboard 2 {% endblock title %}

{% block stylesheets %}
  {{ block.super }}
{% endblock stylesheets %}

{% block content %}
  <div class="right_col" role="main">
    <div class="">
      <div class="row">
        <div class="col-md-12">
          <div class="x_panel">

            <!-- グラフコンテナ カレンダー -->
            <div class="x_title">
              <h2>Transaction Summary <small>Weekly progress</small></h2>
              <div class="filter">
                <div id="reportrange" class="pull-right" style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc">
                  <i class="glyphicon glyphicon-calendar fa fa-calendar"></i>
                  <span>December 30, 2014 - January 28, 2015</span> <b class="caret"></b>
                </div>
              </div>
              <div class="clearfix"></div>
            </div>
            <!-- グラフコンテナ カレンダーここまで -->


            <div class="x_content">
              <div class="col-md-9 col-sm-12 col-xs-12">
                <!-- グラフ -->
                <div class="demo-container" style="height:280px">
                  <div id="chart_plot_02" class="demo-placeholder"></div>
                </div>
                <!-- グラフここまで -->

                <!-- グラフ下のTotal数関係 -->
                <div class="tiles">
                  <div class="col-md-4 tile">
                    <span>Total Sessions</span>
                    <h2>231,809</h2>
                    <span class="sparkline11 graph" style="height: 160px;">
                         <canvas width="200" height="60" style="display: inline-block; vertical-align: top; width: 94px; height: 30px;"></canvas>
                    </span>
                  </div>
                  <div class="col-md-4 tile">
                    <span>Total Revenue</span>
                    <h2>$231,809</h2>
                    <span class="sparkline22 graph" style="height: 160px;">
                          <canvas width="200" height="60" style="display: inline-block; vertical-align: top; width: 94px; height: 30px;"></canvas>
                    </span>
                  </div>
                  <div class="col-md-4 tile">
                    <span>Total Sessions</span>
                    <h2>231,809</h2>
                    <span class="sparkline11 graph" style="height: 160px;">
                           <canvas width="200" height="60" style="display: inline-block; vertical-align: top; width: 94px; height: 30px;"></canvas>
                    </span>
                  </div>
                </div>

              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
{% endblock content %}

{% block javascripts %}
  {{ block.super}}
  <!-- Chart.js -->
  <script src="/static/vendors/Chart.js/dist/Chart.min.js"></script>
  <!-- gauge.js -->
  <script src="/static/vendors/gauge.js/dist/gauge.min.js"></script>
  <!-- Skycons -->
  <script src="/static/vendors/skycons/skycons.js"></script>
  <!-- Flot -->
  <script src="/static/vendors/Flot/jquery.flot.js"></script>
  <script src="/static/vendors/Flot/jquery.flot.pie.js"></script>
  <script src="/static/vendors/Flot/jquery.flot.time.js"></script>
  <script src="/static/vendors/Flot/jquery.flot.stack.js"></script>
  <script src="/static/vendors/Flot/jquery.flot.resize.js"></script>
  <!-- Flot plugins -->
  <script src="/static/vendors/flot.orderbars/js/jquery.flot.orderBars.js"></script>
  <script src="/static/vendors/flot-spline/js/jquery.flot.spline.min.js"></script>
  <script src="/static/vendors/flot.curvedlines/curvedLines.js"></script>
  <!-- DateJS -->
  <script src="/static/vendors/DateJS/build/date.js"></script>
  <!-- JQVMap -->
  <script src="/static/vendors/jqvmap/dist/jquery.vmap.js"></script>
  <script src="/static/vendors/jqvmap/dist/maps/jquery.vmap.world.js"></script>
  <script>
    var chart_plot_02_data = {{ js|safe }}
  </script>
{% endblock javascripts %}
{% endif %}

SQLにDateで格納したカラムの操作ポイント

Django初心者の私が悩んだのは【取り出した値の姿形】でした。
Date形式で保存しているので、SQLを確認すると Y-m-d の姿で収まっています。

これをTemplateに送って展開するとこんな感じの表記になりました。

#template.html

{% for item in data %}
  {{ item.end_date }}
{% endfor %}

#出力結果
2020年11月29日 2020年11月22日 2020年11月15日 2020年11月8日 2020年11月1日 2020年10月25日 ...

で、グラフづくりにテーブル内の全データは必要ないので一部取出して配列に入れて日付が逆順だとグラフが出来ないので並び替え。

#views.py

"""データ成形"""
list_plots = []
for dt in data:
  list_plots.append([dt.observation_date, dt.four_leaves])

""" 並び替え """
list_plots.sort(key=itemgetter(0))

#出力結果
[[datetime.date(2020, 2, 23), 0], [datetime.date(2020, 3, 1), 0], [datetime.date(2020, 3, 8), 1],...

配列に入れると datetime.date(Y, m, d) になってました。
となれば、datetimeをUNIXマイクロ秒に変換すればいいのでpythonのtime関数が使えます。

#views.py

import time
(中略)
"""データ成形"""
list_plots = []
  for dt in data:
    list_plots.append([int(time.mktime(dt.observation_date.timetuple())*1000), dt.four_leaves])

list_plots.sort(key=itemgetter(0))

#出力結果
[[1582383600000, 0], [1582988400000, 0], [1583593200000, 1], [1584198000000, 1],...

一度文字列に変換してからdatetime関数で再変換してunix時間に変換してる人とか色んな情報に出会いましたが、この方法が一番スッキリして理解しやすかったです。

int(time.mktime(変換するカラム.timetuple())*1000

最後の乗算は求められている値がマイクロ秒の時に行う処理で、秒までだったら不要です。

Djangoでの2次元配列の並び替え

2次元配列の並び替えについても ppritを使う方法等、いろんな情報がありましたが、これが一番シンプルでした。

並び変える配列.sort(key=itemgetter(参照する列番号))

ちなみに降順の場合はこちら。

並び変える配列.sort(key=itemgetter(参照する列番号),reverse=True)

reverse=Trueを書き加えるだけ。なんて楽なんだろう。
pythonのソート一覧の公式ページ

まとめ

今回は【unixtime変換】に苦労しました。

検索して調べるとdatetime関数で最初からタイムスタンプ取得して表示を変えるという例が多かった印象です。

まぁあまりマイクロ秒に変換したい人がいないって事かな。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。