12
\$\begingroup\$

In the United States, Daylight Saving Time starts on the second Sunday of March, and ends on the first Sunday of November.

Write the shortest full program, function, or code snippet that does the following:

  • Takes a year as input.
  • Outputs two dates: the date when DST starts, and the date when DST ends.
  • I/O can be with any reasonable method.
  • Behavior with 0 or negative years is undefined for this challenge.

Test cases

Year -> Start, End
2021 -> Mar 14, Nov 07
2022 -> Mar 13, Nov 06
2023 -> Mar 12, Nov 05
2024 -> Mar 10, Nov 03
2025 -> Mar 09, Nov 02
2026 -> Mar 08, Nov 01
2027 -> Mar 14, Nov 07
1    -> Mar 11, Nov 04
1234 -> Mar 12, Nov 05
9999 -> Mar 14, Nov 07
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Differs from When will DST start / end, which asks for the next start/end date of the current year, in a specific format. This challenge does not require a specific format, requires 2 output values, and requires a year as input. \$\endgroup\$
    – bigyihsuan
    Commented Nov 1, 2024 at 18:42
  • \$\begingroup\$ Given the Months are fixed and the year is an input, may we output the two days as integers? (especially if we don't have a "date" type?) \$\endgroup\$ Commented Nov 1, 2024 at 19:45
  • 7
    \$\begingroup\$ Probably noteworthy that this is not when US DST would be rather it's when the current implementation of DST in the US would be on the Gregorian calendar. (e.g. 2001 US DST was from April 1st to October 28th; and e.g. the first Sunday of November in the year one was the 6th [and, of course, US DST didn't exist then]) \$\endgroup\$ Commented Nov 1, 2024 at 19:49
  • 1
    \$\begingroup\$ @JonathanAllan Outputting 2 integers is acceptable. \$\endgroup\$
    – bigyihsuan
    Commented Nov 1, 2024 at 20:42
  • \$\begingroup\$ There is no such thing as Daylight Savings Time with plural Savings. Only Daylight Saving Time with singular Saving exists. You're doubtless thinking of the ACME Savings and Loan Sharks Aquarium. :) \$\endgroup\$
    – tchrist
    Commented Nov 4, 2024 at 16:10

13 Answers 13

5
\$\begingroup\$

Jelly,  21 20  19 bytes

:4:“ıd¢‘_/__3%7+8,1

A monadic Link that accepts the year as a positive integer and yields the days of March and November as a pair of integers.

Try it online! Or see the test-suite.

How?

:4:“ıd¢‘_/__3%7+8,1 - Link: integer Year
:4                  - {Year} integer divide by four
  :                 - integer divide by:
   “ıd¢‘            -   code-page indices = [25, 100, 1]
                        -> [Year//100, Year//400, Year//4]
        _/          - reduce by subtraction
          _         - subtract {Year}
           _3       - subtract three
             %7     - modulo seven
                      -> Delta = (Year//100 - Year//400 - Year//4 - Year - 3) % 7
               +8,1 - add [8, 1]
                      -> [8+Delta, 1+Delta]
\$\endgroup\$
4
\$\begingroup\$

APL (Dyalog APL), 17 bytesSBCS

Full program. Prompts for year and prints (day of March, day of November).

8 1-¯7|1⎕DT⊂⎕11 1

… prompt for number, and

11 1 insert as first first element of list [y,11,1]

1⎕DT convert to day count since 1899-12-31

¯7| mod −7 of that

8 1- subtract that from 8 and 1

Attempt This Online! (embedded in lambda for ease of calling)

\$\endgroup\$
3
\$\begingroup\$

Bash + date, 45 42 bytes

n=$[8-`date +%u -d $1/3/8`];echo $[7+n] $n

Try it online! Link includes test cases. Explanation: +%u gives the day of the week as a number from 1 for Monday to 7 for Sunday, which when subtracted from 8 gives the date of the first Sunday in November; 7 is then added to give the date of the second Sunday in March.

Sadly GNU date's weekday support only seems to work for dates relative to today.

Edit: Saved 3 bytes thanks to @DigitalTrauma.

\$\endgroup\$
3
  • \$\begingroup\$ Also, you can drop the space after -d to save a byte. \$\endgroup\$ Commented Nov 5, 2024 at 20:23
  • \$\begingroup\$ I refactored it to have dc do the arithmetic to save quite a bit more \$\endgroup\$ Commented Nov 5, 2024 at 20:24
  • \$\begingroup\$ @DigitalTrauma Fair enough, but that of course makes it a different language. \$\endgroup\$
    – Neil
    Commented Nov 5, 2024 at 22:26
2
\$\begingroup\$

Factor, 59 bytes

[ <year> march 2 over november 1 [ sunday-of-month ] 2bi@ ]

Try it online!

[         ! a function
<year>    ! create timestamp from integer year input
march     ! change from jan 1 to march 1
2         ! push 2 to indicate we want second sunday
over      ! create a copy of the timestamp on top of stack
november  ! change from march 1 to november 1
1         ! push 1 to indicate we want first sunday

[ sunday-of-month ] 2bi@  ! change both timestamps to nth sunday of month

]         ! end function
\$\endgroup\$
3
  • \$\begingroup\$ Do you need to include the USING (like import in Python)? \$\endgroup\$ Commented Nov 1, 2024 at 23:15
  • 1
    \$\begingroup\$ @JonathanAllan No. \$\endgroup\$
    – chunes
    Commented Nov 1, 2024 at 23:56
  • \$\begingroup\$ Ah, makes sense. \$\endgroup\$ Commented Nov 2, 2024 at 0:00
2
\$\begingroup\$

Python 3.8 (pre-release), 63 bytes

lambda x:(w:=7-date(x,3,1).weekday(),w+7)
from datetime import*

Try it online!

The output is a tuple of the dates (the November date then the March date). This does not work for years >9999.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 67 bytes

y=>[(g=d=>(s=new Date(y+99,-1186,d)).getDay()?g(d-1):s)(14),g(252)]

Try it online!

Silly but works

JavaScript (Node.js), 60 bytes

not support some ancient years(1-2 digits)

y=>[(g=d=>(s=new Date(y,2,d)).getDay()?g(d-1):s)(14),g(252)]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Same length \$\endgroup\$
    – l4m2
    Commented Nov 2, 2024 at 12:48
2
\$\begingroup\$

Python 3.8, 46 bytes

lambda y:[n:=(y//100-y//400-y//4-y-3)%7+8,n-7]

An unnamed function that accepts the year and returns a list of the two days of March and November.

Try it online!


Python 2, 44 bytes

Backport courtesy of Lucenaposition.

lambda y:(y/100-y/400-y/4-y-3)%7*(1+1j)+8+1j

An unnamed function that accepts the year and returns a complex number with the day of March as the real part and the day of November as the imaginary part.

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Thanks @Lucenaposition, added. \$\endgroup\$ Commented Nov 4, 2024 at 19:17
1
\$\begingroup\$

Perl 5 -MDate::Manip -a, 55 bytes

say ParseDate"$_@F"for"2nd sun in mar","1st sun in nov"

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Does not work for years less than 1000 \$\endgroup\$ Commented Nov 1, 2024 at 23:13
  • 1
    \$\begingroup\$ It does, but you need to enter it as four digits (0043). \$\endgroup\$
    – Xcali
    Commented Nov 2, 2024 at 16:24
1
\$\begingroup\$

Charcoal, 30 bytes

NθI⁺⟦⁸¦¹⟧﹪⁻⁺⁴÷θ¹⁰⁰⁺⁺÷θ⁴⁰⁰÷θ⁴θ⁷

Try it online! Link is to verbose version of code. Explanation:

Nθ                              Input year as a number
            ⁴                   Literal integer `4`
           ⁺                    Plus
              θ                 Input year
             ÷                  Integer divided by
               ¹⁰⁰              Literal integer `100`
          ⁻                     Subtract
                     θ          Input year
                    ÷           Integer divided by
                      ⁴⁰⁰       Literal integer `400`
                   ⁺            Plus
                          θ     Input year
                         ÷      Integer divided by
                           ⁴    Literal integer `4`
                  ⁺             Plus
                            θ   Input year
         ﹪                      Modulo
                             ⁷  Literal integer `7`
   ⁺                            Vectorised add
     ⁸                          Literal integer `8`
       ¹                        Literal integer `1`
    ⟦   ⟧                       Make into list
  I                             Cast to string
                                Implicitly print
\$\endgroup\$
1
\$\begingroup\$

Bash + GNU date + GNU dc, 27

Refactored from @Neil's answer to use dc to do the arithmetic.

date +8r%u-d7+f -d$1/3/8|dc

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Shell and zdump on FreeBSD version ≥ 13.2, 45 bytes

How is this still a thing? On a FreeBSD system you do not need to re‑invent the wheel:

zdump -ic`read y;echo $y,$((y+1))` US/Eastern

prints for input 2024


TZ="US/Eastern"
-   -   -05 EST
2024-03-10  03  -04 EDT 1
2024-11-03  01  -05 EST

Spaces are horizontal tabs so their apparent widths depend on your tabs setting. If this concise format is too cryptic for you, try the ‑Verbose format:

zdump -Vc`read y;echo $y,$((y+1))` US/Eastern

prints for input 2024

US/Eastern  Sun Mar 10 06:59:59 2024 UT = Sun Mar 10 01:59:59 2024 EST isdst=0 gmtoff=-18000
US/Eastern  Sun Mar 10 07:00:00 2024 UT = Sun Mar 10 03:00:00 2024 EDT isdst=1 gmtoff=-14400
US/Eastern  Sun Nov  3 05:59:59 2024 UT = Sun Nov  3 01:59:59 2024 EDT isdst=1 gmtoff=-14400
US/Eastern  Sun Nov  3 06:00:00 2024 UT = Sun Nov  3 01:00:00 2024 EST isdst=0 gmtoff=-18000

The date format may differ depending on your locale.
NB: This “program” does (correctly) not work according to specification for years before DST was introduced (y ≤ 1917).

\$\endgroup\$
2
  • \$\begingroup\$ The challenge does require handling all positive years. So either add 2800 to the year or find a different approach. \$\endgroup\$
    – emanresu A
    Commented Nov 3, 2024 at 7:38
  • \$\begingroup\$ @emanresu Well, the wording of the challenge (“Outputs two dates: the date when DST starts, and the date when DST ends.”) and most test cases suggest that the calendar dates of DST becoming effective/ineffective were wanted, but then there are two odd test case of years before 1583 (first complete calendar year after introduction of Gregorian calendar)/1917 (first application of DST) and only the spring: 2nd Mar. wk.—fall: 1st Oct. wk. rule are referenced, which – as Jonathan pointed out in the question comment – is incomplete, so it is not quite clear what the requirements in fact are. \$\endgroup\$ Commented Nov 5, 2024 at 16:00
0
\$\begingroup\$

05AB1E, 16 bytes

тx·4)÷`I3Æ7%81S+

Port of @JonathanAllan's Jelly answer, so make sure to upvote that answer as well!

Try it online or verify all test cases.

Explanation:

т                # Push 100
 x               # Double it (without popping)
  ·              # Pop and double it again
   4             # Push 4
    )            # Wrap all three into a list: [100,400,4]
     ÷           # Integer-divide the (implicit) input-year by these three values
      `          # Pop and push all three to the stack
       I         # Push the input-year
        3        # Push 3
         Æ       # Reduce the stack by subtracting: y//100-y//400-y//4-y-3
          7%     # Modulo-7
            81S  # Push pair [8,1]
               + # Add both to the value
                 # (after which the pair is output implicitly as result)
\$\endgroup\$
0
\$\begingroup\$

Octave, 88 72 bytes

72 bytes, Saved 16 bytes thanks to @ceilingcat

Try it online!

function r=f(y)r=mod(fix(y/100)-fix(y/400)-fix(y/4)-y-3,7)*(1+i)+8+i;end

Original answer:

Try it online!

function r=f(y)r=mod(floor(y/100)-floor(y/400)-floor(y/4)-y-3,7)*(1+1i)+8+1i;endfunction
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.