matahari terbit dan matahari terbenam

12

Saya sedikit romantis, saya suka membawa istri saya keluar untuk melihat matahari terbit dan terbenam di tempat kami berada. Demi latihan ini, katakanlah saya tidak memiliki kode yang dapat memberi tahu saya waktu saat matahari terbenam atau matahari terbit untuk tanggal, lintang dan bujur mana pun saya berada.

Tugas Anda, coders, adalah untuk menghasilkan kode sekecil mungkin yang mengambil lintang dan bujur desimal (diambil dalam derajat N dan W, sehingga derajat S dan E akan dianggap negatif) dan tanggal dalam format YYYY-MM-DD ( mulai 1 Januari 2000 dan seterusnya) dan akan dimuntahkan dua kali dalam format 24 jam untuk matahari terbit dan terbenam.

mis. Untuk hari ini di Sydney, Australia

riseset -33.87 -151.2 2013-12-27

05:45 20:09

Bonus: -100 jika Anda dapat memperhitungkan faktor ketinggian -100 jika Anda dapat faktor penghematan siang hari

Kode HARUS meludahkan waktu di zona waktu relevan yang ditentukan dalam input berdasarkan garis lintang dan bujur ATAU di zona waktu mesin klien sendiri.

WallyWest
sumber
3
Tunggu, apa, kita harus melakukan pencarian [garis lintang x garis bujur] => [zona waktu]? Apakah kita mendapatkan file data untuk itu? Atau server yang bisa kita akses? Atau ada bahasa yang memiliki hal-hal seperti itu? Bisakah Anda memberi tahu kami yang mana? Atau kita harus mengingat batas zona waktu? Untuk presisi apa? Di mana kita mendapatkan data ini? Apakah Anda menyadari bahwa data ini akan menghabiskan sebagian besar panjang kode? Bagaimana dengan koordinat yang jatuh persis di batas zona waktu? Katakanlah, kutub geografisnya? Juga, perilaku apa yang diizinkan ketika input adalah wilayah kutub selama malam / hari kutub? Bagaimana dengan koordinat di luar jangkauan?
John Dvorak
Saya akan senang tantangan untuk menghitung cakrawala berdasarkan pada titik di atas bola ideal, tapi saya benci tantangan terkait untuk menemukan, kompres tangan, dekopmress secara programatis dan kemudian melihat ke dalam, peta pencarian zona waktu. Kecuali, tentu saja, kita dapat menggunakan zona waktu ideal (offset dipilih agar matahari tertinggi pada siang hari, kemudian dibulatkan ke jam terdekat) juga.
John Dvorak
1
@JanDvorak Gunakan apa pun yang Anda bisa, jika bahasa yang Anda gunakan dapat mengeksploitasi zona waktu klien maka dengan segala cara melakukannya ...
WallyWest
1
Apa perilaku yang diinginkan untuk daerah kutub ketika hari / malam kutub?
John Dvorak
1
Berikut adalah alat yang melakukan hal yang persis sama: weatherimages.org/latlonsun.html
Eisa Adil

Jawaban:

4

Saya telah menghabiskan beberapa waktu menulis ini:

#!/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

Sekarang ini belum berfungsi (saya mengacaukan beberapa perhitungan) - Saya akan kembali lagi nanti (jika saya masih memiliki keberanian) untuk menyelesaikannya / berkomentar .

Juga, beberapa sumber menarik yang saya temukan saat meneliti subjek:

Deneb
sumber
3
Saya baru saja melihat komentar Anda tentang # It's late, I'm tired, and OP is a prick for asking me to do this. Tidak ada kewajiban untuk melakukan tugas ini ... Tolong jangan masukkan komentar seperti ini dalam kode Anda ... Itu tidak duduk baik dengan coders lain ... termasuk saya. Saya mengagumi kenyataan bahwa Anda mencobanya, dan tautan lain yang Anda berikan, tetapi jangan gunakan komentar seperti ini lagi ...
WallyWest
@ Eliseod'Annunzio Anda mendapat permintaan maaf saya.
Deneb
@ Eliseod'Annunzio Saya tidak bermaksud menyinggung Anda. Saya juga ingin mengucapkan terima kasih karena telah memberikan saya ide yang sangat fantastis untuk penelitian dan kode. Sekarang saya ingin mengubahnya menjadi modul python yang berdiri sendiri (dengan argumen sys dan sebagainya). Ternyata menjadi sedikit lebih rumit dari yang saya pikirkan sebelumnya, tetapi saya bermaksud untuk melakukannya. Terima kasih lagi.
Deneb
@Alex, apakah Anda menyadari tantangan ini berumur satu tahun? Saya cukup yakin dia menang.
mbomb007
@ mbomb007: Tidak sadar.
Alex A.