<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rishabh Singh</title>
    <description>The latest articles on DEV Community by Rishabh Singh (@rishabh-hub).</description>
    <link>https://dev.to/rishabh-hub</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1075840%2F8cfd3dbf-e756-42f4-9800-b48e628e2ab9.jpeg</url>
      <title>DEV Community: Rishabh Singh</title>
      <link>https://dev.to/rishabh-hub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rishabh-hub"/>
    <language>en</language>
    <item>
      <title>It's Always 05:53 in Kolkata</title>
      <dc:creator>Rishabh Singh</dc:creator>
      <pubDate>Sat, 08 Aug 2026 09:36:44 +0000</pubDate>
      <link>https://dev.to/rishabh-hub/its-always-0553-in-kolkata-1ldm</link>
      <guid>https://dev.to/rishabh-hub/its-always-0553-in-kolkata-1ldm</guid>
      <description>&lt;h3&gt;
  
  
  or, how deleting one dependency taught us more about time than we ever wanted to know
&lt;/h3&gt;




&lt;h2&gt;
  
  
  The setup: "it's basically a find-and-replace"
&lt;/h2&gt;

&lt;p&gt;Every good horror story starts with someone saying it'll be quick.&lt;/p&gt;

&lt;p&gt;Ours started with a dependency. We were upgrading our Django monolith from 4.2 to 5.2, and along the way we needed to get rid of &lt;strong&gt;pytz&lt;/strong&gt;, the timezone library that's been quietly powering Python datetimes since before some of our engineers could walk. Python has shipped a perfectly good timezone library in its standard library since 3.9 (&lt;code&gt;zoneinfo&lt;/code&gt;), pytz has been politely asking everyone to leave since 2020, and Django 5.x has fully moved on. So the task was clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# before
&lt;/span&gt;&lt;span class="n"&gt;tz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Asia/Kolkata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# after
&lt;/span&gt;&lt;span class="n"&gt;tz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zoneinfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ZoneInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Asia/Kolkata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eighty-seven of those across the codebase. A weekend of find-and-replace, a green test suite, a celebratory chai. How hard could it be?&lt;/p&gt;

&lt;p&gt;Reader, it was hard. The swap itself stayed exactly as simple as it looks; the difficulty was in everything underneath it. &lt;strong&gt;Time is a lie we've all agreed to tell&lt;/strong&gt;, and the moment you look at it closely, it looks back. What follows is a field guide to everything that bit us, everything we learned that we genuinely did not know before, and the handful of brilliant people on the internet who had already written down the answers we were about to discover the hard way.&lt;/p&gt;

&lt;p&gt;Grab a chai. This one has a body count.&lt;/p&gt;




&lt;h2&gt;
  
  
  A field guide to why clocks lie
&lt;/h2&gt;

&lt;p&gt;Before the war stories, a crash course, because half our bugs came from assumptions so obvious we never thought to question them. Almost every one of them appears, verbatim, in the two canonical lists every engineer should read once and re-read whenever they feel confident: &lt;strong&gt;"Falsehoods programmers believe about time"&lt;/strong&gt; and its sequel &lt;strong&gt;"...about time zones."&lt;/strong&gt; A tasting menu of things that are simply not true:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Daylight Saving is one hour."&lt;/strong&gt; Usually. Not always. And it's not even called the same thing twice. Americans "spring forward" into &lt;strong&gt;Daylight Saving Time&lt;/strong&gt;; the British and Europeans switch to &lt;strong&gt;Summer Time&lt;/strong&gt; (BST, CEST) and back to &lt;strong&gt;Winter Time&lt;/strong&gt;. During WWII, Britain ran &lt;strong&gt;Double Summer Time&lt;/strong&gt;, a full &lt;em&gt;two&lt;/em&gt; hours ahead of GMT, so factory workers could get home before the blackout. The clocks have been a political instrument for a lot longer than they've been a software bug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"DST makes the clock go forward."&lt;/strong&gt; Meet &lt;strong&gt;Ireland&lt;/strong&gt;, which runs its clocks on &lt;em&gt;negative&lt;/em&gt; DST. By the letter of the Standard Time Act of 1968, &lt;strong&gt;Irish Standard Time is the summer hour&lt;/strong&gt; (the legal baseline), and &lt;em&gt;winter&lt;/em&gt; is the deviation, a one-hour subtraction. So when Dublin "falls back" in October, it's applying negative daylight saving. That is the literal encoding in the tz database, and it wrecked one of our assumptions (more on that later).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Time zone abbreviations identify a zone."&lt;/strong&gt; They do not. &lt;strong&gt;IST&lt;/strong&gt; means Indian Standard Time (+05:30), &lt;em&gt;and&lt;/em&gt; Irish Standard Time (+01:00), &lt;em&gt;and&lt;/em&gt; Israel Standard Time (+02:00). Three continents, three offsets, one abbreviation. Never parse a zone from its abbreviation. Never.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Offsets are whole hours, or at worst half-hours."&lt;/strong&gt; India is +05:30. &lt;strong&gt;Nepal is +05:45&lt;/strong&gt;, a quarter-hour offset that sits, with what we can only assume is deliberate serenity, exactly fifteen minutes ahead of its enormous neighbour. The Chatham Islands are +12:45. If your code assumes offsets are integers, a surprising number of countries are waiting to prove you wrong.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Two dates that are one day apart are one day apart."&lt;/strong&gt; &lt;strong&gt;Kiribati&lt;/strong&gt; shifted its eastern islands across the International Date Line on the last day of 1994, inventing &lt;strong&gt;UTC+14&lt;/strong&gt; and becoming the first place on Earth to see each new day. &lt;strong&gt;Samoa&lt;/strong&gt; did the opposite in 2011: to stop losing two business days a week to the gap between itself and Australia/New Zealand, it &lt;strong&gt;skipped December 30th entirely&lt;/strong&gt;. If you had a Samoan birthday on the 30th that year, tough luck; the day did not happen.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tom Scott summarised the whole genre in one Computerphile video in 2013: a man slowly realising, on camera, that time is a "twisty-turny thing" that leads programmers into madness. We rewatched it mid-migration. It hit different.&lt;/p&gt;

&lt;p&gt;Every one of those bullets is a bug someone shipped, and several of them are bugs &lt;em&gt;we&lt;/em&gt; shipped. Let's meet them.&lt;/p&gt;




&lt;h2&gt;
  
  
  The ghost of 05:53 (a.k.a. the fastest footgun in the west)
&lt;/h2&gt;

&lt;p&gt;Here is a line of code that looks completely fine and is completely wrong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pytz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Asia/Kolkata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'd expect that to be 09:15 in India, i.e. offset &lt;strong&gt;+05:30&lt;/strong&gt;. What you actually get is offset &lt;strong&gt;+05:53&lt;/strong&gt;: twenty-three minutes off, silently, forever.&lt;/p&gt;

&lt;p&gt;Why? Because pytz doesn't work like a normal &lt;code&gt;tzinfo&lt;/code&gt;. When you attach a pytz zone directly via &lt;code&gt;tzinfo=&lt;/code&gt;, it reaches straight past your date for the &lt;strong&gt;first entry in the zone's history&lt;/strong&gt;, which for Kolkata is the &lt;strong&gt;Local Mean Time&lt;/strong&gt; the city kept back when "noon" meant "the sun is overhead" and standardised time zones hadn't been invented yet. Kolkata's solar mean time was about +05:53. So pytz cheerfully hands you a timestamp anchored to a &lt;strong&gt;sundial from the 1800s&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fguljzv73bnl056i6hghk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fguljzv73bnl056i6hghk.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paul Ganssle documented this beautifully in a post titled, no notes, &lt;strong&gt;"pytz: The Fastest Footgun in the West."&lt;/strong&gt; His example is New York, whose ghost offset is &lt;strong&gt;−04:56&lt;/strong&gt; (Manhattan's local mean time). Same trap, different city. His verdict on the library: it makes it "very easy to pytz incorrectly," even when you know exactly how it works. The &lt;em&gt;correct&lt;/em&gt; pytz incantation is &lt;code&gt;tz.localize(dt)&lt;/code&gt; (and &lt;code&gt;tz.normalize()&lt;/code&gt; after any arithmetic, because pytz caches the stale offset). It's an entire ritual that exists purely to work around the footgun. &lt;code&gt;zoneinfo&lt;/code&gt; has no footgun; you just attach it and it does the right thing.&lt;/p&gt;

&lt;p&gt;We found the ghost of 05:53 in three separate places:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In production&lt;/strong&gt;, in &lt;code&gt;booking/tasks.py&lt;/code&gt;, a &lt;code&gt;.replace(tzinfo=pytz(...))&lt;/code&gt; had quietly frozen every slot cursor to +05:53 instead of +05:30. It had been subtly wrong for years. &lt;code&gt;zoneinfo&lt;/code&gt; &lt;em&gt;fixed&lt;/em&gt; it, which is a lovely sentence until you realise "fixing" it also &lt;strong&gt;changes the output&lt;/strong&gt;, which means it can't be a silent swap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In our test data&lt;/strong&gt;, where dozens of assertions expected serialized timestamps like &lt;code&gt;2016-03-11 13:01:00+0553&lt;/code&gt;. Those &lt;code&gt;+0553&lt;/code&gt;s were fossils: the LMT ghost, pinned into our expected values, teaching every new engineer the wrong offset by example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In the CGM subsystem&lt;/strong&gt;, where a glucose event logged at 09:15 got bucketed by &lt;em&gt;hour&lt;/em&gt;. Under the LMT ghost, "09:15" became "08:52" once it hit UTC, so the event landed in &lt;strong&gt;hour 8&lt;/strong&gt;. Correctly interpreted as +05:30, it's &lt;strong&gt;hour 9&lt;/strong&gt;. Our assertion said &lt;code&gt;{8: 1}&lt;/code&gt;; the truth was &lt;code&gt;{9: 1}&lt;/code&gt;. A twenty-three-minute lie, hiding inside a dictionary key.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The lesson we tattooed on the team's collective forearm: &lt;strong&gt;never build an aware datetime by handing a zone to &lt;code&gt;tzinfo=&lt;/code&gt;.&lt;/strong&gt; Not with pytz (you get the ghost), and honestly not as a reflex even with &lt;code&gt;zoneinfo&lt;/code&gt; (where it's correct but where a &lt;code&gt;.localize&lt;/code&gt;-shaped habit is safer). Attach zones with a tool that &lt;em&gt;knows what day it is&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two kinds of broken o'clock: gaps and folds
&lt;/h2&gt;

&lt;p&gt;Twice a year, in most of the world, the clock lies on purpose.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In spring, it &lt;strong&gt;skips an hour&lt;/strong&gt;. 02:00 to 03:00 simply doesn't happen. Any wall-clock time in that hour is a &lt;strong&gt;gap&lt;/strong&gt;, an imaginary time that never existed. Ask for it and a strict library will refuse.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In autumn, it &lt;strong&gt;repeats an hour&lt;/strong&gt;. 01:00 to 02:00 happens &lt;em&gt;twice&lt;/em&gt;. Any wall-clock time in that hour is a &lt;strong&gt;fold&lt;/strong&gt;: ambiguous, two real instants wearing the same face.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Python's answer to this is &lt;strong&gt;PEP 495&lt;/strong&gt;, which added a single attribute to every datetime: &lt;code&gt;fold&lt;/code&gt;. &lt;code&gt;fold=0&lt;/code&gt; means "the first time we saw 01:30"; &lt;code&gt;fold=1&lt;/code&gt; means "the second time." It is, per one blogger, a solution to "the hardest problem in computer science," and it is the quiet hero of the entire &lt;code&gt;zoneinfo&lt;/code&gt; era. But it is &lt;strong&gt;not&lt;/strong&gt; the same as pytz's old &lt;code&gt;is_dst&lt;/code&gt; flag, and assuming they map one-to-one is how you get a very confident, very wrong migration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgcii6fk41vjgtpexjkz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgcii6fk41vjgtpexjkz6.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's where it drew blood. We had a helper that combined a user's date with &lt;strong&gt;midnight&lt;/strong&gt; and attached their timezone. Fine for almost everyone: midnight is a boring, unambiguous time. Except &lt;strong&gt;Cairo and Beirut transition at 00:00&lt;/strong&gt;, where New York and Berlin transition at 02:00. Their DST spring-forward happens &lt;em&gt;at midnight&lt;/em&gt;, which means for those users, on that one day a year, &lt;strong&gt;midnight lands squarely in the gap&lt;/strong&gt;, a time that does not exist. Our code caught &lt;code&gt;AmbiguousTimeError&lt;/code&gt; (the fold) but not &lt;code&gt;NonExistentTimeError&lt;/code&gt; (the gap), so a Cairo user on their spring-forward date got a clean &lt;strong&gt;HTTP 500&lt;/strong&gt;. Once a year. Impossible to reproduce unless you happened to be in Egypt in April.&lt;/p&gt;

&lt;p&gt;And then there's Ireland again. Remember its &lt;strong&gt;negative DST&lt;/strong&gt;? The rule "at an ambiguous fall-back hour, pick standard time" normally means &lt;code&gt;fold=1&lt;/code&gt;. But for a &lt;em&gt;negative&lt;/em&gt;-DST zone like Dublin, standard time is the &lt;em&gt;earlier&lt;/em&gt; reading, so it's &lt;code&gt;fold=0&lt;/code&gt;. We got this backwards once and had to correct it, which is how we learned that "just use fold=1 for standard time" is itself a falsehood programmers believe about time.&lt;/p&gt;

&lt;p&gt;One more trap worth flagging: &lt;strong&gt;&lt;code&gt;make_aware(dt, some_zone)&lt;/code&gt; is not a safe bridge.&lt;/strong&gt; With no explicit flag it behaves like pytz's &lt;code&gt;localize(dt, is_dst=None)&lt;/code&gt;, which &lt;strong&gt;raises&lt;/strong&gt; at ambiguous times, where the old bare &lt;code&gt;.localize(dt)&lt;/code&gt; would have silently shrugged and picked standard. Swap one for the other and you convert a silent success into a loud exception at exactly the two hours a year nobody's testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bugs that only exist on someone else's computer
&lt;/h2&gt;

&lt;p&gt;Some bugs are cowards. They wait until your laptop isn't looking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;utc&lt;/code&gt;/&lt;code&gt;UTC&lt;/code&gt; bug.&lt;/strong&gt; Somewhere in the sweep, &lt;code&gt;pytz.timezone("utc")&lt;/code&gt; became &lt;code&gt;ZoneInfo("utc")&lt;/code&gt;. Looks fine. Passes every test on every developer's Mac. Ships to CI and explodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key utc'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The IANA key is &lt;code&gt;UTC&lt;/code&gt;, uppercase. pytz was case-&lt;em&gt;insensitive&lt;/em&gt; and forgave &lt;code&gt;"utc"&lt;/code&gt;. &lt;code&gt;ZoneInfo&lt;/code&gt; is case-&lt;em&gt;sensitive&lt;/em&gt;. So why did it pass locally? Because &lt;strong&gt;macOS's filesystem is case-insensitive&lt;/strong&gt;, so &lt;code&gt;.../zoneinfo/utc&lt;/code&gt; happily resolved to the &lt;code&gt;UTC&lt;/code&gt; file. Linux, where our CI and our production run, is case-sensitive and does no such favour. This is the purest form of "works on my machine": a bug that is &lt;em&gt;literally invisible&lt;/em&gt; on a Mac and &lt;em&gt;guaranteed&lt;/em&gt; on the server. We now validate every zone literal against &lt;code&gt;zoneinfo.available_timezones()&lt;/code&gt; and never, ever trust a green local run to prove a zone key is real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The country-code that upcased itself.&lt;/strong&gt; pytz has a lookup, &lt;code&gt;pytz.country_timezones&lt;/code&gt;, which quietly &lt;strong&gt;upcases&lt;/strong&gt; your country code before looking it up, so &lt;code&gt;"in"&lt;/code&gt;, &lt;code&gt;"IN"&lt;/code&gt;, and &lt;code&gt;None&lt;/code&gt; all behaved. It has no &lt;code&gt;zoneinfo&lt;/code&gt; equivalent (the standard library simply doesn't ship a country→zone map), so we vendored our own 247-country dictionary. A plain dict, of course, does &lt;em&gt;not&lt;/em&gt; upcase, so &lt;code&gt;map["in"]&lt;/code&gt; returned &lt;code&gt;None&lt;/code&gt;, and our function silently fell back to UTC. And an existing test passed &lt;code&gt;"in"&lt;/code&gt; in lowercase, meaning the lowercase path was real, live, and load-bearing. One &lt;code&gt;.upper()&lt;/code&gt; saved us from telling every lowercase-country-code user they lived in the Atlantic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The one exception that became three.&lt;/strong&gt; pytz folded every possible bad zone name into a single &lt;code&gt;UnknownTimeZoneError&lt;/code&gt;. &lt;code&gt;zoneinfo&lt;/code&gt; splits it into &lt;em&gt;three&lt;/em&gt;: &lt;code&gt;ZoneInfoNotFoundError&lt;/code&gt; for an unknown zone, &lt;code&gt;ValueError&lt;/code&gt; for a malformed one (&lt;code&gt;""&lt;/code&gt;, &lt;code&gt;"../etc/passwd"&lt;/code&gt;, a null byte), and &lt;code&gt;OSError&lt;/code&gt; for one that's absurdly long. We catch this around a &lt;strong&gt;free-text, user-editable timezone field&lt;/strong&gt;, so "catch the one pytz error" would have turned a junk value into a 500 instead of a graceful fallback. One exception became three the day we stopped using pytz, and nobody sends you a memo about that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your timezone database is a time capsule
&lt;/h2&gt;

&lt;p&gt;Here's the one that reframes the whole project.&lt;/p&gt;

&lt;p&gt;pytz ships &lt;strong&gt;data&lt;/strong&gt; as well as code: a snapshot of the world's timezone rules, frozen at whatever version was pinned. Ours was pinned to &lt;code&gt;2022.2.1&lt;/code&gt;. &lt;code&gt;zoneinfo&lt;/code&gt;, by contrast, reads the &lt;strong&gt;live&lt;/strong&gt; &lt;code&gt;tzdata&lt;/code&gt; on the system, which was years newer. So the migration came out offset-neutral for &lt;em&gt;stable&lt;/em&gt; zones and a &lt;strong&gt;correction&lt;/strong&gt; for zones whose rules had changed since 2022:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Egypt&lt;/strong&gt; re-introduced DST in 2023. Under frozen-2022 pytz, Cairo was an hour wrong for half the year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mexico&lt;/strong&gt; abolished most of its DST in 2022. Under frozen pytz, much of the country was an hour wrong the &lt;em&gt;other&lt;/em&gt; half.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tempting framing for the whole migration was "identical behaviour, cleaner imports." The honest one ran longer: &lt;strong&gt;"identical for stable zones, and quietly &lt;em&gt;corrected&lt;/em&gt; for two dozen zones whose governments changed their minds."&lt;/strong&gt; That's a sentence you have to say out loud to the people who read the reports, because a report that shifts by an hour looks like a bug even when it's a fix.&lt;/p&gt;

&lt;p&gt;Why does timezone data drift at all? Because it's a &lt;strong&gt;living record of political whim&lt;/strong&gt;, hand-maintained by volunteers. The &lt;strong&gt;tz database&lt;/strong&gt; (the single source of truth behind pytz, &lt;code&gt;zoneinfo&lt;/code&gt;, your phone, and basically every computer) has been curated since 1986, largely by Arthur David Olson and later Paul Eggert. In 2011 an &lt;strong&gt;astrology software company sued them&lt;/strong&gt;, claiming the historical timezone data was lifted from a copyrighted atlas. The lawsuit (&lt;em&gt;Astrolabe v. Olson&lt;/em&gt;) briefly took the database &lt;em&gt;offline&lt;/em&gt;, the timekeeping backbone of modern computing nearly shut down by people who chart horoscopes, until the EFF stepped in, got it dismissed, and extracted a covenant never to sue again. Your calendar app survives at the pleasure of a volunteer mailing list that once had to lawyer up against astrologers. Update your tzdata.&lt;/p&gt;




&lt;h2&gt;
  
  
  Flip the sources last (and other things you learn by breaking prod)
&lt;/h2&gt;

&lt;p&gt;The single most expensive lesson sits above every zone in this post: &lt;strong&gt;order of operations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Deep in the codebase were a handful of "getter" functions (&lt;code&gt;get_timezone_for_user()&lt;/code&gt; and friends) that returned a zone object. Change those to return &lt;code&gt;zoneinfo&lt;/code&gt; and you're done, right? Except &lt;strong&gt;dozens of call sites downstream still called &lt;code&gt;.localize()&lt;/code&gt; on the result&lt;/strong&gt;, a pytz method that &lt;code&gt;ZoneInfo&lt;/code&gt; does not have. Flip the source first, and every one of those sites detonates with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AttributeError: 'zoneinfo.ZoneInfo' object has no attribute 'localize'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...in production, all at once. (We know because an early PR did exactly this.) The rule we extracted, and now recite: &lt;strong&gt;make the call sites timezone-library-agnostic &lt;em&gt;first&lt;/em&gt;, and flip the sources &lt;em&gt;last&lt;/em&gt;.&lt;/strong&gt; The whole pytz-only surface is exactly three methods: &lt;code&gt;.localize()&lt;/code&gt;, &lt;code&gt;.normalize()&lt;/code&gt;, and &lt;code&gt;.zone&lt;/code&gt;, so we hunt those down and neutralise them everywhere &lt;em&gt;before&lt;/em&gt; the object underneath them changes shape. A related corollary for tests: &lt;strong&gt;a mock that fakes a timezone getter has to return the same &lt;em&gt;kind&lt;/em&gt; of object the real getter now returns.&lt;/strong&gt; Otherwise it either hides a real crash or invents a fake one.&lt;/p&gt;

&lt;p&gt;And a final, humbling footnote. When we declared victory ("&lt;code&gt;import pytz&lt;/code&gt; is zero across the whole repo!"), we were &lt;strong&gt;wrong, twice&lt;/strong&gt;. A reviewer found a stray &lt;code&gt;import pytz&lt;/code&gt; in a file called &lt;code&gt;healthify/untitled&lt;/code&gt;: an ancient Python 2 scratch file (it has &lt;code&gt;print&lt;/code&gt; statements; it cannot even parse under Python 3) with no &lt;code&gt;.py&lt;/code&gt; extension, committed years ago and forgotten. It had no extension, so our &lt;code&gt;*.py&lt;/code&gt; grep never saw it. And &lt;code&gt;git grep&lt;/code&gt;, for reasons involving how git treats extensionless files, &lt;em&gt;also&lt;/em&gt; silently skipped it. Two different searches, both blind to the same file. "Zero pytz" is a claim you should verify with a plain filesystem &lt;code&gt;grep&lt;/code&gt;, not a clever one, because the clever ones have blind spots exactly where the cruft accumulates.&lt;/p&gt;




&lt;h2&gt;
  
  
  The reading list that actually saved us
&lt;/h2&gt;

&lt;p&gt;We owe most of this to people who had already been bitten and had the decency to write it down. If you take one thing from this post, take this list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Paul Ganssle, &lt;a href="https://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html" rel="noopener noreferrer"&gt;pytz: The Fastest Footgun in the West&lt;/a&gt;.&lt;/strong&gt; The definitive explanation of the LMT ghost and why &lt;code&gt;datetime(tzinfo=pytz_zone)&lt;/code&gt; betrays you. Also his &lt;a href="https://blog.ganssle.io/articles/2022/04/naive-local-datetimes.html" rel="noopener noreferrer"&gt;Why naïve times are local times in Python&lt;/a&gt;, which reframes how you think about naïve datetimes entirely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://peps.python.org/pep-0495/" rel="noopener noreferrer"&gt;PEP 495 – Local Time Disambiguation&lt;/a&gt;.&lt;/strong&gt; The &lt;code&gt;fold&lt;/code&gt; attribute, gaps, and folds, straight from the source. Short, and load-bearing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca" rel="noopener noreferrer"&gt;Falsehoods programmers believe about time&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://www.zainrizvi.io/blog/falsehoods-programmers-believe-about-time-zones/" rel="noopener noreferrer"&gt;Falsehoods programmers believe about time zones&lt;/a&gt;.&lt;/strong&gt; Read them before you write your next date-handling function. Then read them again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Back Market Engineering, &lt;a href="https://engineering.backmarket.com/moving-forward-in-pythons-time-and-time-zones-aa3ccbd4569a" rel="noopener noreferrer"&gt;Moving forward in Python's time and time zones&lt;/a&gt;.&lt;/strong&gt; A peer team's writeup of this exact pytz→zoneinfo journey. Reassuring, in a "misery loves company" way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Paul Ganssle's &lt;a href="https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html" rel="noopener noreferrer"&gt;pytz_deprecation_shim&lt;/a&gt;.&lt;/strong&gt; For giant codebases that can't flip everything at once, it emits warnings so you can drain call sites incrementally. We seriously considered it for our worst hotspot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tom Scott / Computerphile, &lt;a href="https://www.youtube.com/watch?v=-5wpm-gesOY" rel="noopener noreferrer"&gt;The Problem with Time &amp;amp; Timezones&lt;/a&gt;.&lt;/strong&gt; Ten minutes, no code, and the best emotional preparation for this work that exists.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.eff.org/cases/astrolabe-v-olson" rel="noopener noreferrer"&gt;Astrolabe v. Olson (EFF)&lt;/a&gt;.&lt;/strong&gt; The time the tz database almost died. Read it and go update your &lt;code&gt;tzdata&lt;/code&gt; out of gratitude.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jon Skeet's &lt;em&gt;"Storing UTC is not a silver bullet"&lt;/em&gt; (on his blog) is the essential counter-sermon for when someone says "just store everything in UTC and you'll be fine." You won't. Not always.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The rules we live by now
&lt;/h2&gt;

&lt;p&gt;If you're about to do this, or just want to stop shipping timezone bugs, here's everything above, distilled:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Store instants, not wall-clock times.&lt;/strong&gt; UTC or epoch for the moment something happened. Attach a human timezone only at the very edges, for display.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Never build an aware datetime with &lt;code&gt;tzinfo=&amp;lt;a named zone&amp;gt;&lt;/code&gt;.&lt;/strong&gt; With pytz it's the LMT ghost; as a habit it's a trap. Use the library's proper "localize" path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Treat every timezone string as untrusted user input.&lt;/strong&gt; It may be miscased (&lt;code&gt;utc&lt;/code&gt;), it may be malformed, it may not exist. Normalize case, validate against the real zone list, and have a fallback that doesn't 500.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Noon is your friend; midnight is a trap.&lt;/strong&gt; If you must pick an arbitrary time of day for a date, pick one that can't fall in a DST gap. Noon never does. Midnight does, in Cairo, once a year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test on the platform you deploy to.&lt;/strong&gt; Your case-insensitive laptop will hide real bugs from you. Trust Linux CI, not a green run on a Mac.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flip the sources last.&lt;/strong&gt; Make call sites library-agnostic before you change what the zone objects are. Hunt &lt;code&gt;.localize&lt;/code&gt; / &lt;code&gt;.normalize&lt;/code&gt; / &lt;code&gt;.zone&lt;/code&gt; to zero first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expect corrections, and announce them.&lt;/strong&gt; Fresh tzdata &lt;em&gt;fixes&lt;/em&gt; stale offsets. A fix that moves a report by an hour still looks like a bug to whoever reads the report. Tell them first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You will not out-clever the tz database.&lt;/strong&gt; Do not hand-maintain a timezone list. Do not parse zones from abbreviations. Do not assume offsets are integers. The database has 40 years and a lawsuit's worth of edge cases you haven't thought of. Defer to it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Coda
&lt;/h2&gt;

&lt;p&gt;We set out to delete a dependency. We came back knowing that Ireland runs its clocks backwards, that Samoa once deleted a Friday, that our own booking system had been quietly living in 1854, and that somewhere on a mailing list a group of volunteers is, right now, encoding some parliament's latest decision about when the sun should be allowed to set.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import pytz&lt;/code&gt; is finally zero. The tests are green, on Linux this time. And every one of us now flinches, just slightly, whenever someone says a datetime task will be quick.&lt;/p&gt;

&lt;p&gt;Time will still find a way. But at least now we know its names.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written after the great &lt;code&gt;pytz&lt;/code&gt;→&lt;code&gt;zoneinfo&lt;/code&gt; migration of 2026. Corrections, additions, and better jokes welcome. This codebase's relationship with time is ongoing.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>timezones</category>
      <category>programming</category>
    </item>
    <item>
      <title>DeepWiki: Complete Guide + Hacks</title>
      <dc:creator>Rishabh Singh</dc:creator>
      <pubDate>Sun, 11 May 2025 12:02:44 +0000</pubDate>
      <link>https://dev.to/rishabh-hub/harnessing-deepwiki-a-developers-guide-to-smarter-code-exploration-30dd</link>
      <guid>https://dev.to/rishabh-hub/harnessing-deepwiki-a-developers-guide-to-smarter-code-exploration-30dd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As a fullstack developer, I've spent countless hours deciphering unfamiliar codebases. It's part of the job, but it's rarely efficient. &lt;br&gt;
Recently, I've been testing DeepWiki – a tool that converts GitHub repositories into interactive documentation hubs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojh89omn2oef3kpegkyt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojh89omn2oef3kpegkyt.png" alt="First page deepwiki" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What DeepWiki does automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 Analyzes repository structure&lt;/li&gt;
&lt;li&gt;📝 Generates documentation based on the code&lt;/li&gt;
&lt;li&gt;📊 Creates visual relationship diagrams&lt;/li&gt;
&lt;li&gt;💬 Offers a natural language interface for questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've found it particularly useful when contributing to open-source projects or understanding complex libraries without extensive documentation. The time saved on initial orientation is substantial.&lt;/p&gt;

&lt;p&gt;This guide shares my practical experience with the free version of DeepWiki, including straightforward steps to integrate it into your workflow and keep the documentation synchronized with repository updates.&lt;/p&gt;

&lt;p&gt;Let's explore how this tool can help fellow independent developers work more efficiently, without the marketing hype.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started with DeepWiki
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The One-Second Setup
&lt;/h3&gt;

&lt;p&gt;Transform any GitHub repository into a wiki by replacing "github.com" with "deepwiki.com":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/username/repository → https://deepwiki.com/username/repository
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo18aqo48p7g55irzck2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo18aqo48p7g55irzck2.png" alt="URL transformation example" width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhw5t3atp2l40i6o5hvd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhw5t3atp2l40i6o5hvd.png" alt="URL transformation example" width="800" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Works in all modern browsers&lt;/li&gt;
&lt;li&gt;Desktop provides better navigation than mobile&lt;/li&gt;
&lt;li&gt;Initial loading takes 20-45 seconds for average repositories&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  First Look: The Interface
&lt;/h3&gt;

&lt;p&gt;When loaded, you'll see three main sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigation Panel&lt;/strong&gt; (Left): Repository file structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Area&lt;/strong&gt; (Center): Documentation and diagrams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask Panel&lt;/strong&gt; (Center bottom): AI assistant for questions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On this Page&lt;/strong&gt; (Right) : Section headings for the current documentation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftecge1mni512xagtur52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftecge1mni512xagtur52.png" alt="Simple labeled interface screenshot" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DeepWiki immediately identifies key files, main functionality, and generates architecture diagrams where possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Features Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Repository Structure Navigation
&lt;/h3&gt;

&lt;p&gt;The left sidebar presents an organized view of your repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigation tree with expandable sections (like "Authentication System," "UI Components")&lt;/li&gt;
&lt;li&gt;Hierarchical organization of subsystems and their components&lt;/li&gt;
&lt;li&gt;Quick access to key interfaces (e.g., "Login Interface," "Replay Upload Interface")&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Auto-Generated Documentation
&lt;/h3&gt;

&lt;p&gt;The center panel provides comprehensive documentation automatically created from your code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Purpose and Scope" summaries explaining what the repository does&lt;/li&gt;
&lt;li&gt;System architecture overviews with integration details&lt;/li&gt;
&lt;li&gt;Component relationships and dependencies clearly outlined&lt;/li&gt;
&lt;li&gt;Direct links to related systems (notice how "Authentication System" is linked)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Visual Diagrams
&lt;/h3&gt;

&lt;p&gt;Automatically generated diagrams visualize code relationships:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Class hierarchies&lt;/li&gt;
&lt;li&gt;Component interactions&lt;/li&gt;
&lt;li&gt;Data flow patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdoyfedviggrnzy67aqs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdoyfedviggrnzy67aqs.png" alt="Example diagram" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask Questions in Natural Language
&lt;/h3&gt;

&lt;p&gt;Ask about the codebase in plain English:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"How is authentication handled?"&lt;/li&gt;
&lt;li&gt;"What does the main function do?"&lt;/li&gt;
&lt;li&gt;"Explain the data models"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DeepWiki highlights relevant code sections and provides contextual explanations based on its analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf73egrf7k5d1y3avkgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf73egrf7k5d1y3avkgb.png" alt="Ask panel with example Q&amp;amp;A" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsb8zvncacqoho5dgmte.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsb8zvncacqoho5dgmte.png" alt="Ask panel with example Q&amp;amp;A" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Techniques 🚀
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Keep Your Wiki Automatically Updated
&lt;/h3&gt;

&lt;p&gt;DeepWiki offers a seamless way to ensure your documentation stays in sync with your codebase:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the official DeepWiki badge to your repository's README file&lt;/li&gt;
&lt;li&gt;This enables automatic weekly refreshes of your DeepWiki documentation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Simply add this markdown to your README:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;![Ask DeepWiki&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://deepwiki.com/badge.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;](https://deepwiki.com/username/repository)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The badge looks like this and links directly to your DeepWiki page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6gx4tx4c5zq4ju315ts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6gx4tx4c5zq4ju315ts.png" alt="DeepWiki badge example" width="244" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the easiest way to ensure your team and contributors always have access to up-to-date documentation without manual refreshes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unlock DeepResearch Mode for Complex Questions
&lt;/h3&gt;

&lt;p&gt;Standard questions are great for quick answers, but for deeper understanding, DeepResearch mode is a game-changer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the "Research" button in the Ask panel&lt;/li&gt;
&lt;li&gt;Pose your complex question&lt;/li&gt;
&lt;li&gt;Watch as the AI conducts a thorough, multi-turn investigation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Real example:&lt;/strong&gt; When I asked about authentication flow, DeepResearch delivered a comprehensive breakdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Ok, now give me details of the auth flow, explaining how it is happening behind the scenes from Google's servers to Supabase and to this app. Draw a flow diagram demonstrating the same"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5uuf1ebtbykbd5r2y0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5uuf1ebtbykbd5r2y0r.png" alt="Deep research question" width="798" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result was a detailed explanation AND a visual flow diagram showing the entire authentication process – from Google OAuth to Supabase token handling to frontend session management.&lt;/p&gt;

&lt;p&gt;Link - &lt;a href="https://deepwiki.com/search/what-modes-of-auth-does-this-r_f9a4e4c1-cec2-43a8-a32c-8a27d2138132#3" rel="noopener noreferrer"&gt;https://deepwiki.com/search/what-modes-of-auth-does-this-r_f9a4e4c1-cec2-43a8-a32c-8a27d2138132#3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jwicea6l0rwwskpsd09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jwicea6l0rwwskpsd09.png" alt="DeepResearch mode showing auth flow diagram" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qycvbpwld8tu68vezn8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qycvbpwld8tu68vezn8.png" alt="DeepResearch mode showing auth flow diagram" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Craft Questions That Get Better Answers
&lt;/h3&gt;

&lt;p&gt;The secret to great results is asking the right way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name specific files: "Explain how src/auth/handlers.js works"&lt;/li&gt;
&lt;li&gt;Request visualizations: "Draw a diagram of the data flow"&lt;/li&gt;
&lt;li&gt;Ask for comparisons: "How does the old API differ from the new one?"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion: Code Exploration Reimagined
&lt;/h2&gt;

&lt;p&gt;DeepWiki has transformed how I approach unfamiliar codebases. What once took hours now takes minutes with AI-powered documentation and targeted questions.&lt;/p&gt;

&lt;p&gt;It shines brightest when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploring open-source projects&lt;/li&gt;
&lt;li&gt;Understanding complex dependencies&lt;/li&gt;
&lt;li&gt;Getting quick overviews of interesting repositories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For maintainers, the README badge feature ensures your documentation stays current with weekly automatic updates – a small addition with significant value for your contributors.&lt;/p&gt;

&lt;p&gt;Your turn takes just one step: Change "github.com" to "deepwiki.com" in any repository URL and unlock immediate insights.&lt;/p&gt;

&lt;p&gt;What will you discover in your next code exploration?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #DeepWiki #DeveloperTools #CodeExploration #OpenSource #AIForDevelopers #SoftwareDevelopment #DevProductivity #CodingTools #TechTutorial #GitHubAlternative #ProgrammingTips #DeveloperExperience #AITools #SoftwareEngineering #TechStack #WebDevelopment #ProgrammingTools #CodeNavigation #DevTools #MustHaveTools&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>productivity</category>
      <category>github</category>
    </item>
  </channel>
</rss>
