พระอาทิตย์ขึ้นและพระอาทิตย์ตก


12

ฉันเป็นคนโรแมนติคฉันชอบพาภรรยาออกไปดูพระอาทิตย์ขึ้นและตกในสถานที่ที่เราอยู่ เพื่อประโยชน์ของการออกกำลังกายนี้สมมติว่าฉันไม่มีรหัสที่สามารถบอกเวลาของพระอาทิตย์ตกหรือพระอาทิตย์ขึ้นสำหรับวันใด ๆ ละติจูดและลองจิจูดฉันจะเกิดขึ้น

งานโคดเดอร์ของคุณคือการสร้างรหัสที่เล็กที่สุดเท่าที่จะเป็นไปได้ซึ่งใช้ละติจูดและลองจิจูดทศนิยม (ถ่ายในองศา N และ W ดังนั้นองศา S และ E จะถูกพิจารณาเป็นเนกาทีฟ) และวันที่ในรูปแบบ YYYY-MM-DD ( ตั้งแต่วันที่ 1 มกราคม 2000 เป็นต้นไป) และจะคายสองครั้งในรูปแบบ 24 ชั่วโมงสำหรับพระอาทิตย์ขึ้นและพระอาทิตย์ตก

เช่นสำหรับวันนี้ในซิดนีย์, ออสเตรเลีย

riseset -33.87 -151.2 2013-12-27

05:45 20:09

โบนัส: -100 ถ้าคุณสามารถแยกตัวในระดับความสูงได้ -100 ถ้าคุณสามารถแยกตัวประกอบการประหยัดเวลากลางวัน

รหัสต้องคายเวลาในเขตเวลาที่เกี่ยวข้องที่ระบุในอินพุตตามละติจูดและลองจิจูดหรือในเขตเวลาของเครื่องไคลเอนต์


3
รออะไรเราต้องทำการค้นหา [ละติจูด x ลองจิจูด] => [เขตเวลา]? เราได้รับไฟล์ข้อมูลสำหรับสิ่งนั้นหรือไม่? หรือเซิร์ฟเวอร์ที่เราสามารถเข้าถึงได้? หรือมีภาษาที่สร้างสิ่งเหล่านี้หรือไม่? คุณบอกเราทีว่าอันไหน หรือเราต้องจดจำขอบเขตเขตเวลา? เพื่อความแม่นยำอะไร เราจะรับข้อมูลนี้ได้ที่ไหน คุณรู้หรือไม่ว่าข้อมูลนี้จะใช้เวลาส่วนใหญ่ของรหัส? แล้วพิกัดที่ตรงกับเขตเวลาจะเป็นอย่างไร พูดแล้วว่าเสาทางภูมิศาสตร์ล่ะ? นอกจากนี้พฤติกรรมใดที่อนุญาตให้ใช้เมื่ออินพุตเป็นพื้นที่ขั้วโลกในช่วงกลางคืนขั้วโลก / วัน? สิ่งที่เกี่ยวกับพิกัดนอกช่วง?
John Dvorak

ฉันจะรักความท้าทายในการคำนวณเส้นขอบฟ้าตามจุดที่อยู่เหนือทรงกลมในอุดมคติ แต่ฉันเกลียดความท้าทายที่เกี่ยวข้องเพื่อค้นหาบีบอัดด้วยมือ decopmress แบบใช้โปรแกรมและค้นหาแผนที่การค้นหาเขตเวลา เว้นแต่แน่นอนเราสามารถใช้เขตเวลาที่เหมาะ (การชดเชยถูกเลือกเพื่อให้ดวงอาทิตย์สูงที่สุดในช่วงเที่ยงจากนั้นจะถูกปัดเศษเป็นชั่วโมงที่ใกล้ที่สุด) เช่นกัน
John Dvorak

1
@JanDvorak ใช้ทุกสิ่งที่คุณสามารถทำได้หากภาษาที่คุณใช้สามารถใช้ประโยชน์จากเขตเวลาของลูกค้าได้โดยวิธีการทั้งหมด ...
WallyWest

1
พฤติกรรมที่ต้องการสำหรับพื้นที่ขั้วโลกเมื่อเป็นกลางวัน / กลางคืนคืออะไร?
John Dvorak

1
นี่คือเครื่องมือที่ทำสิ่งเดียวกัน: weatherimages.org/latlonsun.html
Eisa Adil

คำตอบ:


4

ฉันใช้เวลาพอสมควรเขียนสิ่งนี้:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from math import *


class RiseSet(object):

    __ZENITH = {'official': 90.833,
                'civil': '96',
                'nautical': '102',
                'astronomical': '108'}

    def __init__(self, day, month, year, latitude, longitude, daylight=False,
                 elevation=840, zenith='official'):
        ''' elevation is set to 840 (m) because that is the mean height of land above the sea level '''

        if abs(latitude) > 63.572375290155:
            raise ValueError('Invalid latitude: {0}.'.format(latitude))

        if zenith not in self.__ZENITH:
            raise ValueError('Invalid zenith value, must be one of {0}.'.format
                            (self.__ZENITH.keys()))

        self.day = day
        self.month = month
        self.year = year
        self.latitude = latitude
        self.longitude = longitude
        self.daylight = daylight
        self.elevation = elevation
        self.zenith = zenith

    def getZenith(self):
        return cos(radians(self.__ZENITH[self.zenith]))

    def dayOfTheYear(self):
        n0 = floor(275*self.month/9)
        n1 = floor((self.month + 9) / 12)
        n2 = (1 + floor((self.year - 4*floor(self.year/4) + 2) / 3))
        return n0 - (n1*n2) + self.day - 30

    def approxTime(self):
        sunrise = self.dayOfTheYear() + ((6 - (self.longitude/15.0)) / 24)
        sunset = self.dayOfTheYear() + ((18 - (self.longitude/15.0)) / 24)
        return (sunrise, sunset)

    def sunMeanAnomaly(self):
        sunrise = (0.9856 * self.approxTime()[0]) - 3.289
        sunset = (0.9856 * self.approxTime()[1]) - 3.289
        return (sunrise, sunset)

    def sunTrueLongitude(self):
        sma = self.sunMeanAnomaly()
        sunrise = sma[0] + (1.916*sin(radians(sma[0]))) + \
                  (0.020*sin(radians(2*sma[0]))) + 282.634

        if sunrise < 0:
            sunrise += 360
        if sunrise > 360:
            sunrise -= 360

        sunset = sma[1] + (1.916*sin(radians(sma[1]))) + \
                 (0.020*sin(radians(2*sma[1]))) + 282.634

        if sunset <= 0:
            sunset += 360
        if sunset > 360:
            sunset -= 360

        return (sunrise, sunset)

    def sunRightAscension(self):
        stl = self.sunTrueLongitude()
        sunrise = atan(radians(0.91764*tan(radians(stl[0]))))

        if sunrise <= 0:
            sunrise += 360
        if sunrise > 360:
            sunrise -= 360

        sunset = atan(radians(0.91764*tan(radians(stl[1]))))

        if sunset <= 0:
            sunset += 360
        if sunset > 360:
            sunset -= 360

        sunrise_stl_q = (floor(stl[0]/90)) * 90
        sunrise_ra_q = (floor(sunrise/90)) * 90
        sunrise = sunrise + (sunrise_stl_q - sunrise_ra_q)
        sunrise = sunrise/15.0

        sunset_stl_q = (floor(stl[1]/90)) * 90
        sunset_ra_q = (floor(sunset/90)) * 90
        sunset = sunrise + (sunset_stl_q - sunset_ra_q)
        sunset /= 15.0

        return (sunrise, sunset)

    def sunDeclination(self):
        sunrise_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[0]))
        sunrise_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))

        sunset_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[1]))
        sunset_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))

        return (sunrise_sin_dec, sunrise_cos_dec,
                sunset_sin_dec, sunset_cos_dec)

    def sunHourAngle(self):
        sd = self.sunDeclination()
        sunrise_cos_h = (cos(radians(self.getZenith())) - (sd[0]* \
                         sin(radians(self.latitude))) / (sd[1]* \
                         cos(radians(self.latitude))))
        if sunrise_cos_h > 1:
            raise Exception('The sun never rises on this location.')

        sunset_cos_h = (cos(radians(self.getZenith())) - (sd[2]* \
                         sin(radians(self.latitude))) / (sd[3]* \
                         cos(radians(self.latitude))))
        if sunset_cos_h < -1:
            raise Exception('The sun never sets on this location.')

        sunrise = 360 - acos(radians(sunrise_cos_h))
        sunrise /= 15.0

        sunset = acos(radians(sunrise_cos_h))
        sunset /= 15.0

        return (sunrise, sunset)

    def localMeanTime(self):
        sunrise = self.sunHourAngle()[0] + self.sunRightAscension()[0] - \
                 (0.06571*self.approxTime()[0]) - 6.622
        sunset = self.sunHourAngle()[1] + self.sunRightAscension()[1] - \
                 (0.06571*self.approxTime()[1]) - 6.622
        return (sunrise, sunset)

    def convertToUTC(self):
        sunrise = self.localMeanTime()[0] - (self.longitude/15.0)

        if sunrise <= 0:
            sunrise += 24
        if sunrise > 24:
            sunrise -= 24

        sunset = self.localMeanTime()[1] - (self.longitude/15.0)

        if sunset <= 0:
            sunset += 24
        if sunset > 24:
            sunset -= 24

        return (sunrise, sunset)

    def __str__(self):
        return None

ตอนนี้ก็ยังไม่ได้ทำงาน (ฉันเมาขึ้นคำนวณบางอย่าง) - ฉันจะกลับมาได้ในภายหลัง (ถ้าฉันจะยังคงมีความกล้าหาญ) เพื่อดำเนินการได้ / แสดงความคิดเห็นมัน

นอกจากนี้ยังมีแหล่งข้อมูลที่น่าสนใจที่ฉันค้นพบขณะทำการค้นคว้าเรื่อง:


3
ฉันเพิ่งเห็นความคิดเห็นของคุณ# It's late, I'm tired, and OP is a prick for asking me to do this. ไม่มีข้อผูกมัดที่จะทำงานนี้ ... กรุณาอย่าใส่ความคิดเห็นแบบนี้ในรหัสของคุณ ... มันไม่ได้นั่งอยู่กับผู้ให้รหัสอื่น ๆ ... รวมถึงฉันด้วย ฉันชื่นชมความจริงที่ว่าคุณให้มันร้อนแดงไปแล้วและลิงค์อื่น ๆ ที่คุณให้ แต่โปรดอย่าใช้ความเห็นเช่นนี้อีกเลย ...
WallyWest

@ Eliseod'Annunzio คุณมีคำขอโทษของฉัน
Deneb

@ Eliseod'Annunzio ฉันไม่ได้ตั้งใจจะรุกรานคุณ ฉันขอขอบคุณที่ให้แนวคิดที่ยอดเยี่ยมในการวิจัยและรหัสแก่ฉัน ตอนนี้ฉันต้องการเปลี่ยนให้เป็นโมดูล python แบบยืนตัวเอง (พร้อมอาร์กิวเมนต์ sys เป็นต้น) ดูเหมือนจะซับซ้อนกว่าที่ฉันเคยคิดไว้เล็กน้อย แต่ฉันตั้งใจจะถอดมันออก ขอขอบคุณอีกครั้ง.
Deneb

@ อเล็กซ์คุณรู้ไหมว่าความท้าทายนี้มีอายุหนึ่งปีแล้วหรือยัง ฉันค่อนข้างแน่ใจว่าเขาชนะ
mbomb007

@ mbomb007: ไม่เข้าใจ
Alex A.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.