2

How to determine which day is the first in week in current locale in C. In Russia monday is the first day, but my mac shows localized calendar with wrong first day. So i wonder if i can determine which day is the first in current locale. Thanks.

anatoly@mb:/Users/anatoly$ cal
     Июля 2012
вс пн вт ср чт пт сб
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Korniltsev Anatoly
  • 3,676
  • 2
  • 26
  • 37
  • Looks like `cal` localization is only about translation of days and months, and not whether first day of week is monday, sunday or saturday. – mouviciel Jul 10 '12 at 09:03
  • look like it is, but are you sure, that there is no way to determine which day is the first in ANCI C. I posted cal outpu just as example. – Korniltsev Anatoly Jul 10 '12 at 09:04
  • possible duplicate of [Determine what day of week the week starts with](http://stackoverflow.com/questions/11351196/determine-what-day-of-week-the-week-starts-with) – t0mm13b Jul 10 '12 at 23:05
  • Just as a note: `cal` shows wrong first day because it uses the `_NL_TIME_FIRST_WEEKDAY` method which doesn't seem to be provided on MacOS. On glibc systems, `cal` would start on Monday. – Michał Górny Jul 13 '12 at 07:04
  • As far as i know mac does not come with glibc at all. It uses another libc (don't know which) and there is no _NL_TIME_FIRST_WEEKDAY in headers at all, so I ended up with #if !defined(__GLIBC__) return 1; #else return *nl_langinfo(_NL_TIME_FIRST_WEEKDAY); #endif – Korniltsev Anatoly Jul 13 '12 at 07:12

3 Answers3

8

With glibc, you can do:

#define _GNU_SOURCE
#include <langinfo.h>

char get_first_weekday()
{
    return *nl_langinfo(_NL_TIME_FIRST_WEEKDAY);
}

Remember to call setlocale() first. Example:

#include <stdio.h>
#include <locale.h>

int main()
{
    setlocale(LC_ALL, "");
    printf("%d\n", get_first_weekday());
    return 0;
}

This returns 2 on my system (which means monday == DAY_2).

Just a note: I don't think it's public API of glibc. However, this is how locale tool bundled with it gets first weekday. cal uses similar method as well.

Depending on a particular use, you may be interested in _NL_TIME_FIRST_WORKDAY as well.

Michał Górny
  • 18,713
  • 5
  • 53
  • 76
1

I was wrong in my first post, and ICU provides a C API.

So, if dependency on that library is acceptable for you, you can get the first of the week portably using the following snippet:

#include <stdio.h>

/* for calendar functions */
#include <unicode/ucal.h>
/* for u_cleanup() */
#include <unicode/uclean.h>
/* for uloc_getDefault() */
#include <unicode/uloc.h>

int main()
{
    /* it *has* to be pre-set */
    UErrorCode err = U_ZERO_ERROR;

    UCalendar* cal = ucal_open(
            0, -1, /* default timezone */
            uloc_getDefault(), /* default (current) locale */
            UCAL_DEFAULT, /* default calendar type */
            &err);

    if (!cal)
    {
        fprintf(stderr, "ICU error: %s\n", u_errorName(err));
        u_cleanup();
        return 1;
    }

    /* 1 for sunday, 2 for monday, etc. */
    printf("%d\n", ucal_getAttribute(cal, UCAL_FIRST_DAY_OF_WEEK));

    ucal_close(cal);
    u_cleanup();
    return 0;
}

Then you link the program with icu-i18n pkg-config library.

Ah, and they have quite an extensive example printing a calendar, if you might be interested.

Michał Górny
  • 18,713
  • 5
  • 53
  • 76
  • It was a kind of a "test-task" so it didnot matter what library to use. However it is really strange i could not find it in google. Do you use the library or you just found it? – Korniltsev Anatoly Aug 13 '12 at 06:32
  • Well, I knew about it because it was pulled in to my system by boost. However, I've just noticed in another post that ICU actually has a C API as well (not only the C++ one). – Michał Górny Aug 13 '12 at 08:06
0

Apparently on Macs you can use:

#include <ApplicationServices/ApplicationServices.h>
[..]
CFCalendarRef cal = CFCalendarCopyCurrent();  
long first_day = CFCalendarGetFirstWeekday(cal); // 1=Sunday, ..
CFRelease(cal); 

Source: [1].

erco
  • 272
  • 1
  • 8