<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Asiones Jia's blog]]></title><description><![CDATA[Asiones Jia's blog]]></description><link>https://asiones.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1672501340578/GYrnZYQXz.png</url><title>Asiones Jia&apos;s blog</title><link>https://asiones.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 03 May 2026 04:22:35 GMT</lastBuildDate><atom:link href="https://asiones.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[tailwindcss variables not working in Chrome extension]]></title><description><![CDATA[How to fix it
/* If your code is like this in global.css */
@layer base {
    :root {
        --background: 0 0% 100%;
        --foreground: 222.2 47.4% 11.2%;
        /* 
        ...
        */
    }
}

/* Try this instead: 'Change :root to :host' *...]]></description><link>https://asiones.hashnode.dev/tailwindcss-variables-not-working-in-chrome-extension</link><guid isPermaLink="true">https://asiones.hashnode.dev/tailwindcss-variables-not-working-in-chrome-extension</guid><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[shadcn]]></category><category><![CDATA[React]]></category><category><![CDATA[chrome extension]]></category><dc:creator><![CDATA[Asiones Jia]]></dc:creator><pubDate>Wed, 18 Dec 2024 13:06:08 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-how-to-fix-it">How to fix it</h3>
<pre><code class="lang-css"><span class="hljs-comment">/* If your code is like this in global.css */</span>
<span class="hljs-keyword">@layer</span> base {
    <span class="hljs-selector-pseudo">:root</span> {
        <span class="hljs-attribute">--background</span>: <span class="hljs-number">0</span> <span class="hljs-number">0%</span> <span class="hljs-number">100%</span>;
        <span class="hljs-attribute">--foreground</span>: <span class="hljs-number">222.2</span> <span class="hljs-number">47.4%</span> <span class="hljs-number">11.2%</span>;
        <span class="hljs-comment">/* 
        ...
        */</span>
    }
}

<span class="hljs-comment">/* Try this instead: 'Change :root to :host' */</span>
<span class="hljs-keyword">@layer</span> base {
    <span class="hljs-selector-pseudo">:host</span> {
        <span class="hljs-attribute">--background</span>: <span class="hljs-number">0</span> <span class="hljs-number">0%</span> <span class="hljs-number">100%</span>;
        <span class="hljs-attribute">--foreground</span>: <span class="hljs-number">222.2</span> <span class="hljs-number">47.4%</span> <span class="hljs-number">11.2%</span>;
        <span class="hljs-comment">/* 
        ...
        */</span>
    }
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Eslint warning  Classname 'xxx' is not a Tailwind CSS class!  tailwindcss/no-custom-classname when using shadcn/ui]]></title><description><![CDATA[How to fix it
Just add a rule in lint file.
// .eslintrc
"rules": {
    /**
    ...
    **/
    "tailwindcss/no-custom-classname": "off"
},

Why do this?
https://github.com/shadcn-ui/ui/blob/ea677cc74eb0b35591e06558af80cfce2c5b926b/.eslintrc.json#L14...]]></description><link>https://asiones.hashnode.dev/eslint-warning-classname-xxx-is-not-a-tailwind-css-class-tailwindcssno-custom-classname-when-using-shadcnui</link><guid isPermaLink="true">https://asiones.hashnode.dev/eslint-warning-classname-xxx-is-not-a-tailwind-css-class-tailwindcssno-custom-classname-when-using-shadcnui</guid><category><![CDATA[shadcn ui]]></category><category><![CDATA[eslint]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Asiones Jia]]></dc:creator><pubDate>Wed, 18 Dec 2024 12:57:57 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-how-to-fix-it">How to fix it</h3>
<p>Just add a rule in lint file.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// .eslintrc</span>
<span class="hljs-string">"rules"</span>: {
    <span class="hljs-comment">/**
    ...
    **/</span>
    <span class="hljs-string">"tailwindcss/no-custom-classname"</span>: <span class="hljs-string">"off"</span>
},
</code></pre>
<h3 id="heading-why-do-this">Why do this?</h3>
<p><a target="_blank" href="https://github.com/shadcn-ui/ui/blob/ea677cc74eb0b35591e06558af80cfce2c5b926b/.eslintrc.json#L14">https://github.com/shadcn-ui/ui/blob/ea677cc74eb0b35591e06558af80cfce2c5b926b/.eslintrc.json#L14</a></p>
]]></content:encoded></item><item><title><![CDATA[Incremental data loading with useActionState and yield in Nextjs 15]]></title><description><![CDATA[A few days ago, I had a fucking dream that useActionState can use yield to push data. It was probably that state was an array []. Every time data was yielded in the action function, the data would be appended to the state. (It could also be that I se...]]></description><link>https://asiones.hashnode.dev/incremental-data-loading-with-useactionstate-and-yield-in-nextjs-15</link><guid isPermaLink="true">https://asiones.hashnode.dev/incremental-data-loading-with-useactionstate-and-yield-in-nextjs-15</guid><category><![CDATA[useActionState]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Next.js 15]]></category><category><![CDATA[incremental data loading]]></category><dc:creator><![CDATA[Asiones Jia]]></dc:creator><pubDate>Tue, 29 Oct 2024 19:33:54 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>A few days ago, I had a fucking dream that useActionState can use yield to push data. It was probably that state was an array []. Every time data was yielded in the action function, the data would be appended to the state. (It could also be that I seemed to have seen the code for this implementation somewhere, but I couldn't find it after searching for a whole day.)</p>
</blockquote>
<p>Coincidentally, my business scenario today coincided with this implementation method, and I also successfully implemented Incremental data with useActionState and yield in Nextjs 15.</p>
<h2 id="heading-final-effect">Final effect</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/bx8GjyUvu6o">https://youtu.be/bx8GjyUvu6o</a></div>
<p> </p>
<h2 id="heading-code">Code</h2>
<pre><code class="lang-typescript"><span class="hljs-comment">// actions.ts</span>
<span class="hljs-string">'use server'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">fetchDataAction</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">1</span>, message: <span class="hljs-string">'Step1'</span>, error: <span class="hljs-literal">null</span> }
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>))
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">2</span>, message: <span class="hljs-string">'Step2'</span>, error: <span class="hljs-literal">null</span> }
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>))
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">3</span>, message: <span class="hljs-string">'Step3'</span>, error: <span class="hljs-literal">null</span> }
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>))
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">4</span>, message: <span class="hljs-string">'Step4'</span>, error: <span class="hljs-literal">null</span> }
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>))
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">5</span>, message: <span class="hljs-string">'Step5'</span>, error: <span class="hljs-literal">null</span> }
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>))
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">6</span>, message: <span class="hljs-string">'Step6'</span>, error: <span class="hljs-literal">null</span> }
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>))
  <span class="hljs-keyword">yield</span> { index: <span class="hljs-number">7</span>, message: <span class="hljs-string">'Step7'</span>, error: <span class="hljs-literal">null</span> }
}
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-comment">// page.tsx</span>
<span class="hljs-string">'use client'</span>
<span class="hljs-keyword">import</span> { useActionState, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { fetchDataAction } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/actions'</span>

<span class="hljs-keyword">type</span> PageProps = {}

<span class="hljs-keyword">const</span> Page = <span class="hljs-function">(<span class="hljs-params">{}: PageProps</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [currentStep, setCurrentStep] = useState&lt;{
    index: <span class="hljs-built_in">number</span> | <span class="hljs-literal">null</span> | <span class="hljs-literal">undefined</span>
    message: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span> | <span class="hljs-literal">undefined</span>
    error: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span> | <span class="hljs-literal">undefined</span>
  }&gt;({ index: <span class="hljs-number">0</span>, message: <span class="hljs-literal">null</span>, error: <span class="hljs-literal">null</span> })
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState&lt;<span class="hljs-built_in">boolean</span>&gt;(<span class="hljs-literal">true</span>)
  <span class="hljs-keyword">const</span> [state, formAction] = useActionState(fetchDataAction, <span class="hljs-literal">undefined</span>)

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> stepItr = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> next = <span class="hljs-keyword">await</span> state?.next()
      <span class="hljs-keyword">const</span> value = next?.value
      <span class="hljs-keyword">const</span> done = next?.done
      <span class="hljs-keyword">if</span> (done) {
        setLoading(<span class="hljs-literal">false</span>)
        <span class="hljs-keyword">return</span>
      }
      setCurrentStep({ index: value?.index, message: value?.message, error: value?.error })
      <span class="hljs-built_in">console</span>.log(value)
      stepItr()
    }
    <span class="hljs-keyword">if</span> (state) {
      stepItr()
      setLoading(<span class="hljs-literal">true</span>)
    }
  }, [state])
  <span class="hljs-keyword">return</span> (
    &lt;div&gt;
      &lt;p&gt;
        Current Step Index: {currentStep?.index || <span class="hljs-string">'No Index...'</span>}
      &lt;/p&gt;
      &lt;p&gt;
        Current Step Message: {currentStep?.message || <span class="hljs-string">'No Message...'</span>}
      &lt;/p&gt;
      &lt;p&gt;
        Current Step <span class="hljs-built_in">Error</span>: {currentStep?.error || <span class="hljs-string">'No Error...'</span>}
      &lt;/p&gt;
      &lt;button
        formAction={formAction}
      &gt;
        Start
      &lt;/button&gt;
    &lt;/div&gt;
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Page
</code></pre>
<p>I'm not sure if this will be a problem in production, if there are any please reply to point them out.</p>
]]></content:encoded></item><item><title><![CDATA[Python实现长度16位十进制整数的客制化雪花算法(Snowflake)生成器]]></title><description><![CDATA[前言
Javascript 整数表达最大为 2^53-1 位，大约是十进制16位，超过就会导致精度丢失，一般在浏览器中会直接报错。
场景
我们知道，雪花算法(SnowFlake)生成的雪花ID是 2^64 位，如果直接使用雪花算法(SnowFlake)生成器，前端是没办法直接拿到int类型的雪花ID，需要后端先将其转换为string类型才行。
使用雪花算法(SnowFlake)的很重要一个原因就是，int类型对数据库索引是很友好的，为了前后端数据交互方便，在数据库中直接储存string类型的雪花...]]></description><link>https://asiones.hashnode.dev/pythonsnowflake</link><guid isPermaLink="true">https://asiones.hashnode.dev/pythonsnowflake</guid><category><![CDATA[Python]]></category><category><![CDATA[snowflake]]></category><dc:creator><![CDATA[Asiones Jia]]></dc:creator><pubDate>Wed, 28 Dec 2022 19:14:05 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-5ymn6kia">前言</h3>
<p>Javascript 整数表达最大为 2^53-1 位，大约是十进制16位，超过就会导致精度丢失，一般在浏览器中会直接报错。</p>
<h3 id="heading-5zy65pmv">场景</h3>
<p>我们知道，雪花算法(SnowFlake)生成的雪花ID是 2^64 位，如果直接使用雪花算法(SnowFlake)生成器，前端是没办法直接拿到int类型的雪花ID，需要后端先将其转换为string类型才行。</p>
<p>使用雪花算法(SnowFlake)的很重要一个原因就是，int类型对数据库索引是很友好的，为了前后端数据交互方便，在数据库中直接储存string类型的雪花ID是让我无法接受的，那么摆在我面前我能想到的只有两个解决方案：</p>
<ol>
<li><p>在每次向前端发送包含雪花ID数据时，先将雪花ID转换为string类型后再进行发送。</p>
</li>
<li><p>缩短雪花ID，使其不超过 2^53-1 位。</p>
</li>
</ol>
<p>我选择第二个解决方案。</p>
<h3 id="heading-6yen5paw6k66k6h6zuq6iqx566x5rov">重新设计雪花算法</h3>
<p>首先重新设计雪花ID：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672252277151/340c59fb-f754-4ab1-b6a2-d667ddd8cd9d.jpeg" alt class="image--center mx-auto" /></p>
<ul>
<li><p>41位，时间戳，精确到毫秒，最大值为 2^41 ，一年有 3.1556926 × 10<sup>10</sup> 毫秒，2^41/3.1556926 × 10<sup>10</sup> 大约等于69年。</p>
</li>
<li><p>4位，我定义它4位来表示机器ID，最高可以容纳16台机器。由于是分布式，我们避免不了有很多机器，但在我的项目里，16台机器已经够用了。（当然，你可以让它为5位，6位……</p>
</li>
<li><p>3位，我定义它3位来表示服务ID，最高可以容纳8个服务。在我的项目里，不仅用户uid会使用到雪花ID，订单ID，流水号等都可能会使用到雪花算法来生成序列号。（当然，你可以让它为4位，5位……</p>
</li>
<li><p>5位，最大可容纳32个序列号，在同一机器同一服务同一毫秒内产生的ID通过该序号进行累加区分。</p>
</li>
</ul>
<p>其实除了前41位时间戳，后面的12位均可以自定义，我的需求是这样，故我定义它为这样。</p>
<h3 id="heading-5a6e546w5luj56cb">实现代码</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-comment"># 项目元年时间戳</span>
START_TIMESTAMP = <span class="hljs-number">166666666666</span>

<span class="hljs-comment"># 机器ID bit位数</span>
MACHINE_ID_BITS = <span class="hljs-number">4</span>

<span class="hljs-comment"># 服务ID bit位数</span>
SERVICE_ID_BITS = <span class="hljs-number">3</span>

<span class="hljs-comment"># 序号 bit位数</span>
SEQUENCE_BITS = <span class="hljs-number">5</span>

<span class="hljs-comment"># 机器ID最大值计算</span>
MAX_MACHINE_ID = (<span class="hljs-number">1</span> &lt;&lt; MACHINE_ID_BITS) - <span class="hljs-number">1</span>

<span class="hljs-comment"># 服务ID最大值计算</span>
MAX_SERVICE_ID = (<span class="hljs-number">1</span> &lt;&lt; SERVICE_ID_BITS) - <span class="hljs-number">1</span>

<span class="hljs-comment"># 序号掩码最大值</span>
MAX_SEQUENCE = (<span class="hljs-number">1</span> &lt;&lt; SEQUENCE_BITS) - <span class="hljs-number">1</span>

<span class="hljs-comment"># 移位偏移值计算</span>
SERVICE_ID_SHIFT = SEQUENCE_BITS
MACHINE_ID_SHIFT = SEQUENCE_BITS + SERVICE_ID_BITS
TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + SERVICE_ID_BITS + MACHINE_ID_BITS


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SnowFlake</span>:</span>
    <span class="hljs-string">"""
    用于生成IDs
    """</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, machine_id, service_id, sequence=<span class="hljs-number">0</span></span>):</span>
        <span class="hljs-string">"""
        初始化
        :param machine_id: 机器ID
        :param service_id: 服务ID
        :param sequence: 序号掩码
        """</span>
        <span class="hljs-comment"># 校验机器ID</span>
        <span class="hljs-keyword">if</span> machine_id &gt; MAX_MACHINE_ID <span class="hljs-keyword">or</span> machine_id &lt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">'机器ID值越界'</span>)

        <span class="hljs-comment"># 校验服务ID</span>
        <span class="hljs-keyword">if</span> service_id &gt; MAX_SERVICE_ID <span class="hljs-keyword">or</span> service_id &lt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">'服务ID值越界'</span>)

        self.machine_id = machine_id
        self.service_id = service_id
        self.sequence = sequence

        self.last_timestamp = <span class="hljs-number">-1</span>  <span class="hljs-comment"># 上次计算的时间戳</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_gen_timestamp</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        生成整数时间戳
        :return:int timestamp
        """</span>
        <span class="hljs-keyword">return</span> int(time.time() * <span class="hljs-number">1000</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_id</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""
        生成ID
        :return:int
        """</span>
        timestamp = self._gen_timestamp()

        <span class="hljs-comment"># 时钟回拨</span>
        <span class="hljs-keyword">if</span> (self.last_timestamp - timestamp) &gt; <span class="hljs-number">3</span>:
            <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">'时钟回拨'</span>)
        <span class="hljs-keyword">if</span> self.last_timestamp &gt; timestamp:
            timestamp = self._til_next_millis(self.last_timestamp)

        <span class="hljs-keyword">if</span> timestamp == self.last_timestamp:
            self.sequence = self.sequence + <span class="hljs-number">1</span>
            <span class="hljs-keyword">if</span> self.sequence &gt; MAX_SEQUENCE:
                timestamp = self._til_next_millis(self.last_timestamp)
                self.sequence = <span class="hljs-number">0</span>
        <span class="hljs-keyword">else</span>:
            self.sequence = <span class="hljs-number">0</span>

        self.last_timestamp = timestamp

        <span class="hljs-comment"># 核心计算</span>
        new_id = ((timestamp - START_TIMESTAMP) &lt;&lt; TIMESTAMP_LEFT_SHIFT) | (self.machine_id &lt;&lt; MACHINE_ID_SHIFT) | \
                 (self.service_id &lt;&lt; SERVICE_ID_SHIFT) | self.sequence

        <span class="hljs-keyword">return</span> new_id

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_til_next_millis</span>(<span class="hljs-params">self, last_timestamp</span>):</span>
        <span class="hljs-string">"""
        等到下一毫秒
        """</span>
        timestamp = self._gen_timestamp()
        <span class="hljs-keyword">while</span> timestamp &lt;= last_timestamp:
            timestamp = self._gen_timestamp()
        <span class="hljs-keyword">return</span> timestamp

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">parse_id</span>(<span class="hljs-params">self, to_be_parsed_id: int</span>):</span>
        <span class="hljs-string">"""
        解析ID
        """</span>
        binary = bin(to_be_parsed_id)
        sequence = int(binary[-SERVICE_ID_SHIFT:], <span class="hljs-number">2</span>)
        service_id = int(binary[-MACHINE_ID_SHIFT:-SERVICE_ID_SHIFT], <span class="hljs-number">2</span>)
        machine_id = int(binary[-TIMESTAMP_LEFT_SHIFT:-MACHINE_ID_SHIFT], <span class="hljs-number">2</span>)
        timestamp = int(binary[:-TIMESTAMP_LEFT_SHIFT], <span class="hljs-number">2</span>) + START_TIMESTAMP
        date_time = datetime.fromtimestamp(timestamp / <span class="hljs-number">1000</span>)

        <span class="hljs-keyword">return</span> {
            <span class="hljs-string">"timestamp"</span>: date_time,
            <span class="hljs-string">"machine_id"</span>: machine_id,
            <span class="hljs-string">"service_id"</span>: service_id,
            <span class="hljs-string">"sequence"</span>: sequence
        }


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    GneSFID = SnowFlake(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>)
    start_timestamp = int(time.time() * <span class="hljs-number">1000</span>)
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1000000</span>):
        print(GneSFID.generate_id())
    end_timestamp = int(time.time() * <span class="hljs-number">1000</span>)
    waste_time = (end_timestamp - start_timestamp) / <span class="hljs-number">1000</span>
    print(waste_time)
</code></pre>
<p>经测试，上面的雪花算法生成100w条雪花ID需要花费大约32s。每毫秒生成的ID 100w/(32*1000) 大约也是等于32，即序列号为32bit满载。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672253676418/fa260803-377f-4634-82e6-c5a55b74569b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-5oyw5z2r8jyhq">挖坑😅</h3>
<p>最后，如果你的初始元年时间戳值离当前时间很近的话，会导致最后生成的雪花ID只有14或者15位，这是因为生成ID的时间戳与元年时间戳差值太小，在二进制中就表现为前面很多0，也就不起作用，同时也无法起到占位的作用。</p>
<p>为了统一长度，可以这样做，将长度不够16位的ID前面用0补充占位。</p>
<p>然后我就发现用 <code>zfill()</code> 补完0从<code>str</code>转为<code>int</code>后，0又消失不见了😵‍💫</p>
<h3 id="heading-parseid-id">更新：新增 <code>parse_id()</code> 解析ID方法</h3>
<p>代码更新在了上面的<a class="post-section-overview" href="#heading-5a6e546w5luj56cb">实现代码</a>。</p>
<p>该方法接收一个 <code>to_be_parsed_id: int</code> 参数，解析后返回一个 <code>dict</code> 。</p>
<p>方法使用示例:</p>
<pre><code class="lang-python"><span class="hljs-comment"># ...省略 class SnowFlake</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    GneSFID = SnowFlake(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>)
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">100000</span>):
        snow_id = GneSFID.generate_id()
        print(snow_id, <span class="hljs-string">'--&gt;'</span>, GenSFID.parse_id(snow_id))
</code></pre>
<blockquote>
<p>如果这片文章对你有帮助的话，请给我点个赞吧👍🏼，就在你的屏幕右上方(手机底部)的😊按钮。</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Fastapi receive a xlsx file and read it]]></title><description><![CDATA[How to accept a xlsx file and read it using Fastapi, the following is the implementation code.
@application.post("/uploadFile/")
async def create_upload_file(file: UploadFile):
    if file.filename.endswith('.xlsx'):
        # Read it, 'f' type is by...]]></description><link>https://asiones.hashnode.dev/fastapi-receive-a-xlsx-file-and-read-it</link><guid isPermaLink="true">https://asiones.hashnode.dev/fastapi-receive-a-xlsx-file-and-read-it</guid><category><![CDATA[FastAPI]]></category><category><![CDATA[excel]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Asiones Jia]]></dc:creator><pubDate>Mon, 31 Oct 2022 17:26:13 GMT</pubDate><content:encoded><![CDATA[<p>How to accept a xlsx file and read it using Fastapi, the following is the implementation code.</p>
<pre><code>@application.post(<span class="hljs-string">"/uploadFile/"</span>)
<span class="hljs-keyword">async</span> def create_upload_file(file: UploadFile):
    <span class="hljs-keyword">if</span> file.filename.endswith(<span class="hljs-string">'.xlsx'</span>):
        # Read it, <span class="hljs-string">'f'</span> type is bytes
        f = <span class="hljs-keyword">await</span> file.read()
        xlsx = io.BytesIO(f)
        wb = openpyxl.load_workbook(xlsx)
        ws = wb[<span class="hljs-string">'Sheet1'</span>]

        <span class="hljs-keyword">for</span> cells <span class="hljs-keyword">in</span> ws.iter_rows():
            print([cell.value <span class="hljs-keyword">for</span> cell <span class="hljs-keyword">in</span> cells])
        <span class="hljs-keyword">return</span> True

    <span class="hljs-attr">else</span>:
        raise HTTPException(status_code=status.HTTP_405_METHOD_NOT_ALLOWED)
</code></pre>]]></content:encoded></item></channel></rss>