1. 17
  1.  

    1. 9

      Another common epoch is Julian day ( https://en.wikipedia.org/wiki/Julian_day ). It starts January 1, 4713 BC. It was created 1583 AD for converting between various calendars, and was successfully used for this purpose to this day. The date January 1, 4713 BC was chosen such way that it is before all written history. Thus every day in written history is encoded as positive number

      1. 2

        At work one of our suppliers uses this on boxes they ship out. Took me a while to figure out what they meant by ‘date’ on one of their boxes

        1. 1

          According to Wikipedia’s list of languages by first written account, the first written accounts were in 2600 BC. So why did they choose 4713 BC?

          1. 5

            Your question is answered in the Wikipedia article, but the short version is that Scaliger was working on assembling a coherent timeline so that dates from various written records could be meaningfully related to each other. In particular, regnal dates were very common, but they don’t give you an absolute date unless you know the monarch’s date of accession. Scaliger matched up events that were recorded in multiple dating systems so he could place those dating systems on his Julian timeline.

            Scaliger based his timeline on three important cycles used in the Julian calendar:

            • The cycle of weeks and leap years, 28 years long.

            • The metonic cycle of lunar months and years used for calculating the date of Easter, 19 years.

            • The indiction cycle, which was an important bureaucratic period maintained for many centuries in the Byzantine empire, 15 years.

            Project those back until they line up, and you get the start of the Julian period.

            There are recorded dates that go back before the first writing, such as the genealogies in the book of Genesis, and these biblical timelines were of interest to scholars such as Scaliger. Those genealogies go back to about 4000 BC.

            (When I originally learned about the Julian period, I was puzzled by the indiction cycle: the solar and lunar cycles are obviously calendrically important, but why did this obscure bureaucratic period matter? Much later on I found a better explanation, which said more explicitly that the indiction was not obscure back then: it was maintained consistently over a very large area for a very long period of time; it was used in accounting and finance and a lot of written records are about keeping track of money; so the indiction cycle was very useful for Scaliger’s purposes.)

            1. [Comment removed by author]

          2. 5
            • C locales are the work of the Devil.
            • Another common epoch is 1/1/2001, used by Apple’s frameworks.
            1. 8

              Apple’s frameworks are also work of the Devil. I once naively assumed that stringifying a NSDate using a specifically given HH:mm format would actually use this format. Like because I requested it. However, Apple decided they knew better what I need… [1]

              In iOS, however, if the user has switched 24-Hour Time to Off, the time may be 1:00 pm.

            2. 3

              Note that at least the Linux glibc manpage for mktime() is pretty vague

              Linux manpages for kernel and glibc interfaces are maintained here: https://www.kernel.org/doc/man-pages/ .

              Unfortunately they are currently in state “if you need something, write a patch”

              1. 2

                This article also serves as yet another proof of why C should not be used for full-blown applications. C’s only purpose today is to be glue between other programs, to be a universal ABI ( https://faultlore.com/blah/c-isnt-a-language/ ) and for writing small programs, which call right syscalls in right order.

                For other purposes you should use other languages. In particular, if you want system programming language (i. e. language, which closely works with OS or hardware), you should pick Rust or Zig

                1. 2

                  C’s only purpose today is to be glue between other programs, to be a universal ABI ( https://faultlore.com/blah/c-isnt-a-language/ )

                  Though for this role the language itself it not needed. C itself is not glue, just the ABIs that were created for it. A Java program can use a Rust library via C FFI without a single C compiler being involved.

                  1. 2

                    Oops, I just discovered that rust bindgen uses clang for parsing C headers. So, my post is partially false

                    1. 2

                      I forgot to reply to when you replied 8 days ago.

                      I think most of the complexity with C headers wouldn’t be used if you used C as a pure IDL. No preprocessor, just plain struct and function declarations. We shouldn’t need to care about “real world” C headers for the purpose of using C as just an IDL for non-C languages.

                    2. 1

                      Yes, but…

                      Though for this role the language itself it not needed

                      Yes

                      Java program can use a Rust library via C FFI without a single C compiler being involved

                      Not necessary.

                      I don’t know Java. But I know Rust. So I will assume for the remainder of this post that Java FFI situation is similar to Rust. :)

                      In Rust there is 2 methods to deal with C ABI. First way: you simply declare function prototype in Rust using Rust language. Such prototype looks similar to C language, but “similar” doesn’t mean “identical”. Such prototype cannot be parsed by C compiler, it can be parsed by Rust compiler only. Second way: you write actual C language prototype in C and then use a tool called “bindgen” to translate that prototype to Rust. This way you have actual C prototype that can be parsed by C compiler.

                      Okay, now let’s imagine we connect Rust and Java. Java and Rust should somehow agree on API/ABI of a function. As I said above, I don’t know how Java works, so I assume that everything I know about Rust applies to Java, too. Okay, so I see two ways:

                      • We declare prototypes in Rust and in Java. If we chose this way, then there is no any automatic way to make sure they match. So programmer should manually inspect them to be sure they match. This is obviously bad solution
                      • We declare prototype in C. Then we translate it to Rust using bindgen and also translate to Java using Java’s bindgen analog. This is obviously better, because we don’t need to manually check anything

                      Okay, so far, so good. Just use bindgen, and all will be good. Right? No! The problem is that real-world C headers are insanely complex. If this C header in question is written specially for this purpose, then, yes, bindgen will successfully parse it, and all will be ok. But if we take some real world C header, then bindgen can break on it. C headers are so complex, that for actual correctness you need real C compiler for parsing it.

                      So bindgen is perpetually unfinished software. It have to add more and more C features, and it never will be done. Bindgen have to perpetually to play wack-a-mole with C compilers. You never can trust bindgen. So Rust’s choice of bindgen was wrong. They should have real C compiler instead.

                      I once found an article that calls people using bindgen “bindgen believers”. I. e. author of that article sarcastically said that bindgen should not be trusted. Unfortunately I lost that link.

                      Take a look at Zig. Zig doesn’t use anything like bindgen. When Zig need to call C, it uses real C compiler (clang) to parse header. So Zig’s approach are correct here, Rust’s is not. Similarly Mojo’s approach is correct. They use clang, too.

                      And article https://faultlore.com/blah/c-isnt-a-language/ talks about all this in section “You Can’t Actually Parse A C Header”.

                      Okay, so, again, if you call between Rust and Java, then, yes, okay, you can go without C compiler. Because you probably wrote that C header yourself, it is probably nice and tiny and bindgen can parse it correctly. But in many other situations where you have real world C header (if, for example, you want to call some real C library from other language), you have to use real C compiler to parse that header.

                      (I wrote this post in hurry. If you don’t understand something, ask, I will explain)

                    3. 2

                      Does Zig have better facilities for handling time? (I haven’t used it)

                      1. 2

                        Not really. There is support for timestamps and monotonic timers in the standard library. Date times and parsing are a problem for third parties and there are no obvious victors yet.

                        https://ziggit.dev/t/state-of-datetime-handling-in-zig/2149/10

                        cc: @safinaskar

                        1. 1

                          I haven’t used it, either :)